diff options
author | Ron Yorston <rmy@pobox.com> | 2017-02-08 20:09:29 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2017-02-08 20:09:29 +0000 |
commit | 373275a708bafb88fa4f0519de2166154f44fed9 (patch) | |
tree | 4587b4fd3f695e0f3705b2a217e199f3144df931 /networking | |
parent | b74b2619779b1deb903b7766261807df1e9b1f7f (diff) | |
parent | c2b18583a3df06aeecf535c3cea6856aa1f2e205 (diff) | |
download | busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.gz busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.bz2 busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
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 | ||
1148 | int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1154 | int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1149 | #if !BB_MMU | ||
1150 | int ftpd_main(int argc, char **argv) | ||
1151 | #else | ||
1152 | int ftpd_main(int argc UNUSED_PARAM, char **argv) | 1155 | int 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: "<Hello World>". | 185 | //config: "<Hello World>". |
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 */ |
1683 | static void FAST_FUNC machtime_stream(int s, servtab_t *sep UNUSED_PARAM) | 1683 | static 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 | |||
23 | int ssl_client_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
24 | int 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 |
405 | static void put_iac_naws(byte c, int x, int y) | 410 | static 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 |
542 | static void to_naws(void) | 547 | static 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 | |||
170 | enum { | ||
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 | |||
224 | struct record_hdr { | ||
225 | uint8_t type; | ||
226 | uint8_t proto_maj, proto_min; | ||
227 | uint8_t len16_hi, len16_lo; | ||
228 | }; | ||
229 | |||
230 | struct 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 | |||
245 | static unsigned get24be(const uint8_t *p) | ||
246 | { | ||
247 | return 0x100*(0x100*p[0] + p[1]) + p[2]; | ||
248 | } | ||
249 | |||
250 | #if TLS_DEBUG | ||
251 | static 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 | |||
260 | static 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 | |||
290 | void 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 */ | ||
297 | static 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 | |||
303 | static 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 | ||
312 | static 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. | ||
342 | typedef struct hmac_precomputed { | ||
343 | md5sha_ctx_t hashed_key_xor_ipad; | ||
344 | md5sha_ctx_t hashed_key_xor_opad; | ||
345 | } hmac_precomputed_t; | ||
346 | |||
347 | static 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 | |||
370 | static 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? | ||
403 | static 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 | |||
436 | static 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 | |||
455 | static 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. | ||
501 | static 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 | |||
542 | static 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 | |||
556 | static 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 | ||
564 | static 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 | |||
574 | static void tls_free_outbuf(tls_state_t *tls) | ||
575 | { | ||
576 | free(tls->outbuf); | ||
577 | tls->outbuf_size = 0; | ||
578 | tls->outbuf = NULL; | ||
579 | } | ||
580 | |||
581 | static 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 | |||
593 | static 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 | |||
743 | static 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 | |||
762 | static 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 | |||
776 | static 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 | |||
791 | static 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 | |||
803 | static 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 | */ | ||
952 | static 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 | |||
994 | static 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 | |||
1004 | static 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 | |||
1014 | static 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 | |||
1025 | static 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 | */ | ||
1164 | static 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 | |||
1181 | static 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 | |||
1195 | static 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 | |||
1287 | static 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 | |||
1373 | static 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 | |||
1403 | static 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 | |||
1423 | static 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 | |||
1544 | static const uint8_t rec_CHANGE_CIPHER_SPEC[] = { | ||
1545 | RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01, | ||
1546 | 01 | ||
1547 | }; | ||
1548 | |||
1549 | static 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. | ||
1592 | static 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 | |||
1621 | void 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 | |||
1726 | static 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 | |||
1741 | void 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 | |||
64 | typedef uint64_t uint64; | ||
65 | typedef int64_t int64; | ||
66 | typedef uint32_t uint32; | ||
67 | typedef int32_t int32; | ||
68 | typedef uint16_t uint16; | ||
69 | typedef 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 | |||
81 | void 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 | |||
8 | static | ||
9 | int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey); | ||
10 | static | ||
11 | void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, | ||
12 | psAesKey_t *skey); | ||
13 | static | ||
14 | void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, | ||
15 | psAesKey_t *skey); | ||
16 | static | ||
17 | int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, | ||
18 | const unsigned char *key, uint32 keylen); | ||
19 | static | ||
20 | int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt, | ||
21 | unsigned char *ct, uint32 len); | ||
22 | static | ||
23 | int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct, | ||
24 | unsigned char *pt, uint32 len); | ||
25 | |||
26 | void 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 | |||
37 | void 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 | /* | ||
95 | Te0[x] = S [x].[02, 01, 01, 03]; | ||
96 | Te1[x] = S [x].[03, 02, 01, 01]; | ||
97 | Te2[x] = S [x].[01, 03, 02, 01]; | ||
98 | Te3[x] = S [x].[01, 01, 03, 02]; | ||
99 | Te4[x] = S [x].[01, 01, 01, 01]; | ||
100 | |||
101 | Td0[x] = Si[x].[0e, 09, 0d, 0b]; | ||
102 | Td1[x] = Si[x].[0b, 0e, 09, 0d]; | ||
103 | Td2[x] = Si[x].[0d, 0b, 0e, 09]; | ||
104 | Td3[x] = Si[x].[09, 0d, 0b, 0e]; | ||
105 | Td4[x] = Si[x].[01, 01, 01, 01]; | ||
106 | */ | ||
107 | |||
108 | static 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 | |||
175 | static 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 | |||
242 | static 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 | |||
309 | static 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 | |||
406 | static 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 | }; | ||
472 | static 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 | }; | ||
538 | static 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 | |||
606 | static const uint32 Te4_0[] = { | ||
607 | 0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, | ||
608 | 0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, | ||
609 | 0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, | ||
610 | 0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, | ||
611 | 0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, | ||
612 | 0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, | ||
613 | 0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, | ||
614 | 0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, | ||
615 | 0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, | ||
616 | 0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, | ||
617 | 0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, | ||
618 | 0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, | ||
619 | 0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, | ||
620 | 0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, | ||
621 | 0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, | ||
622 | 0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, | ||
623 | 0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, | ||
624 | 0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, | ||
625 | 0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, | ||
626 | 0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, | ||
627 | 0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, | ||
628 | 0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, | ||
629 | 0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, | ||
630 | 0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, | ||
631 | 0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, | ||
632 | 0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, | ||
633 | 0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, | ||
634 | 0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, | ||
635 | 0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, | ||
636 | 0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, | ||
637 | 0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, | ||
638 | 0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL | ||
639 | }; | ||
640 | |||
641 | static const uint32 Te4_1[] = { | ||
642 | 0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, | ||
643 | 0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, | ||
644 | 0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, | ||
645 | 0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, | ||
646 | 0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, | ||
647 | 0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, | ||
648 | 0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, | ||
649 | 0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, | ||
650 | 0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, | ||
651 | 0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, | ||
652 | 0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, | ||
653 | 0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, | ||
654 | 0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, | ||
655 | 0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, | ||
656 | 0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, | ||
657 | 0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, | ||
658 | 0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, | ||
659 | 0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, | ||
660 | 0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, | ||
661 | 0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, | ||
662 | 0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, | ||
663 | 0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, | ||
664 | 0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, | ||
665 | 0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, | ||
666 | 0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, | ||
667 | 0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, | ||
668 | 0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, | ||
669 | 0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, | ||
670 | 0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, | ||
671 | 0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, | ||
672 | 0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, | ||
673 | 0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL | ||
674 | }; | ||
675 | |||
676 | static const uint32 Te4_2[] = { | ||
677 | 0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, | ||
678 | 0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, | ||
679 | 0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, | ||
680 | 0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, | ||
681 | 0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, | ||
682 | 0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, | ||
683 | 0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, | ||
684 | 0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, | ||
685 | 0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, | ||
686 | 0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, | ||
687 | 0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, | ||
688 | 0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, | ||
689 | 0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, | ||
690 | 0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, | ||
691 | 0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, | ||
692 | 0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, | ||
693 | 0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, | ||
694 | 0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, | ||
695 | 0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, | ||
696 | 0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, | ||
697 | 0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, | ||
698 | 0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, | ||
699 | 0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, | ||
700 | 0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, | ||
701 | 0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, | ||
702 | 0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, | ||
703 | 0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, | ||
704 | 0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, | ||
705 | 0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, | ||
706 | 0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, | ||
707 | 0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, | ||
708 | 0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL | ||
709 | }; | ||
710 | |||
711 | static const uint32 Te4_3[] = { | ||
712 | 0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, | ||
713 | 0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, | ||
714 | 0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, | ||
715 | 0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, | ||
716 | 0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, | ||
717 | 0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, | ||
718 | 0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, | ||
719 | 0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, | ||
720 | 0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, | ||
721 | 0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, | ||
722 | 0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, | ||
723 | 0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, | ||
724 | 0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, | ||
725 | 0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, | ||
726 | 0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, | ||
727 | 0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, | ||
728 | 0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, | ||
729 | 0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, | ||
730 | 0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, | ||
731 | 0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, | ||
732 | 0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, | ||
733 | 0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, | ||
734 | 0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, | ||
735 | 0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, | ||
736 | 0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, | ||
737 | 0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, | ||
738 | 0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, | ||
739 | 0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, | ||
740 | 0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, | ||
741 | 0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, | ||
742 | 0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, | ||
743 | 0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL | ||
744 | }; | ||
745 | |||
746 | static 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 | }; | ||
812 | static 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 | }; | ||
878 | static 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 | |||
945 | static const uint32 Tks0[] = { | ||
946 | 0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, | ||
947 | 0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, | ||
948 | 0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, | ||
949 | 0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, | ||
950 | 0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, | ||
951 | 0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, | ||
952 | 0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, | ||
953 | 0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, | ||
954 | 0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, | ||
955 | 0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, | ||
956 | 0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, | ||
957 | 0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, | ||
958 | 0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, | ||
959 | 0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, | ||
960 | 0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, | ||
961 | 0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, | ||
962 | 0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, | ||
963 | 0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, | ||
964 | 0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, | ||
965 | 0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, | ||
966 | 0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, | ||
967 | 0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, | ||
968 | 0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, | ||
969 | 0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, | ||
970 | 0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, | ||
971 | 0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, | ||
972 | 0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, | ||
973 | 0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, | ||
974 | 0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, | ||
975 | 0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, | ||
976 | 0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, | ||
977 | 0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL | ||
978 | }; | ||
979 | |||
980 | static const uint32 Tks1[] = { | ||
981 | 0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, | ||
982 | 0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, | ||
983 | 0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, | ||
984 | 0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, | ||
985 | 0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, | ||
986 | 0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, | ||
987 | 0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, | ||
988 | 0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, | ||
989 | 0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, | ||
990 | 0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, | ||
991 | 0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, | ||
992 | 0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, | ||
993 | 0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, | ||
994 | 0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, | ||
995 | 0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, | ||
996 | 0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, | ||
997 | 0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, | ||
998 | 0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, | ||
999 | 0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, | ||
1000 | 0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, | ||
1001 | 0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, | ||
1002 | 0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, | ||
1003 | 0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, | ||
1004 | 0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, | ||
1005 | 0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, | ||
1006 | 0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, | ||
1007 | 0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, | ||
1008 | 0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, | ||
1009 | 0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, | ||
1010 | 0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, | ||
1011 | 0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, | ||
1012 | 0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL | ||
1013 | }; | ||
1014 | |||
1015 | static const uint32 Tks2[] = { | ||
1016 | 0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, | ||
1017 | 0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, | ||
1018 | 0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, | ||
1019 | 0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, | ||
1020 | 0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, | ||
1021 | 0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, | ||
1022 | 0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, | ||
1023 | 0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, | ||
1024 | 0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, | ||
1025 | 0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, | ||
1026 | 0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, | ||
1027 | 0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, | ||
1028 | 0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, | ||
1029 | 0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, | ||
1030 | 0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, | ||
1031 | 0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, | ||
1032 | 0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, | ||
1033 | 0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, | ||
1034 | 0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, | ||
1035 | 0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, | ||
1036 | 0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, | ||
1037 | 0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, | ||
1038 | 0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, | ||
1039 | 0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, | ||
1040 | 0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, | ||
1041 | 0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, | ||
1042 | 0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, | ||
1043 | 0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, | ||
1044 | 0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, | ||
1045 | 0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, | ||
1046 | 0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, | ||
1047 | 0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL | ||
1048 | }; | ||
1049 | |||
1050 | static const uint32 Tks3[] = { | ||
1051 | 0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, | ||
1052 | 0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, | ||
1053 | 0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, | ||
1054 | 0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, | ||
1055 | 0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, | ||
1056 | 0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, | ||
1057 | 0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, | ||
1058 | 0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, | ||
1059 | 0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, | ||
1060 | 0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, | ||
1061 | 0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, | ||
1062 | 0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, | ||
1063 | 0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, | ||
1064 | 0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, | ||
1065 | 0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, | ||
1066 | 0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, | ||
1067 | 0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, | ||
1068 | 0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, | ||
1069 | 0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, | ||
1070 | 0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, | ||
1071 | 0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, | ||
1072 | 0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, | ||
1073 | 0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, | ||
1074 | 0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, | ||
1075 | 0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, | ||
1076 | 0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, | ||
1077 | 0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, | ||
1078 | 0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, | ||
1079 | 0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, | ||
1080 | 0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, | ||
1081 | 0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, | ||
1082 | 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL | ||
1083 | }; | ||
1084 | |||
1085 | #endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ | ||
1086 | |||
1087 | static 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 | ||
1094 | static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, | ||
1095 | psAesKey_t *skey); | ||
1096 | static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, | ||
1097 | psAesKey_t *skey); | ||
1098 | #endif | ||
1099 | |||
1100 | static 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 | ||
1109 | static 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 | ||
1122 | static //bbox | ||
1123 | int32 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 | |||
1150 | static //bbox | ||
1151 | int32 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 | |||
1201 | static //bbox | ||
1202 | int32 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 | |||
1269 | static //bbox | ||
1270 | int32 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 | ||
1437 | static //bbox | ||
1438 | void 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 | } | ||
1444 | static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, | ||
1445 | psAesKey_t *skey) | ||
1446 | #else | ||
1447 | static //bbox | ||
1448 | void 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 | ||
1604 | static //bbox | ||
1605 | void 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 | } | ||
1611 | static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, | ||
1612 | psAesKey_t *skey) | ||
1613 | #else | ||
1614 | static //bbox | ||
1615 | void 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 | |||
9 | void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst); | ||
10 | void 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 | |||
50 | static 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 | */ | ||
56 | int32 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 | */ | ||
83 | int32 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 | */ | ||
114 | int32 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 | */ | ||
150 | int32 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 | */ | ||
207 | void 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 | */ | ||
223 | void 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 | */ | ||
251 | void 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 | */ | ||
280 | void 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 | */ | ||
299 | int32 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 | */ | ||
339 | int32 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 | */ | ||
367 | int32 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 | */ | ||
388 | int32 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 | */ | ||
463 | int16 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 | /******************************************************************************/ | ||
485 | int32 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 | /******************************************************************************/ | ||
492 | void 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 | */ | ||
503 | void 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 | */ | ||
532 | int32 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 | */ | ||
585 | int32 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 | */ | ||
619 | int32 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 | */ | ||
685 | int32 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 | */ | ||
725 | static 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 | */ | ||
782 | int32 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 | */ | ||
827 | int32 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 | */ | ||
845 | int32 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 | */ | ||
881 | int32 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 | */ | ||
919 | static 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 | */ | ||
964 | static 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 | */ | ||
1000 | int32 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 | */ | ||
1035 | int32 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; | ||
1107 | LBL_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 | */ | ||
1121 | int32 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 | */ | ||
1169 | int32 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) | ||
1211 | static 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) | ||
1242 | typedef unsigned long uint128 __attribute__ ((mode(TI))); | ||
1243 | static 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 | */ | ||
1277 | int32 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 | |||
1476 | LBL_Q:pstm_clear (&q); | ||
1477 | LBL_Y:pstm_clear (&y); | ||
1478 | LBL_X:pstm_clear (&x); | ||
1479 | LBL_T2:pstm_clear (&t2); | ||
1480 | LBL_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 | */ | ||
1490 | void 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 | */ | ||
1503 | int32 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 | */ | ||
1530 | int32 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 | */ | ||
1563 | int32 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; | ||
1790 | LBL_MARRAY: | ||
1791 | for (x = 1<<(winsize-1); x < (1 << winsize); x++) { | ||
1792 | pstm_clear(&M[x]); | ||
1793 | } | ||
1794 | LBL_PAD:psFree(paD, pool); | ||
1795 | LBL_M: pstm_clear(&M[1]); | ||
1796 | LBL_RES:pstm_clear(&res); | ||
1797 | return err; | ||
1798 | } | ||
1799 | |||
1800 | /******************************************************************************/ | ||
1801 | /* | ||
1802 | |||
1803 | */ | ||
1804 | int32 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 | */ | ||
1845 | static 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 | */ | ||
1865 | int32 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 | */ | ||
1890 | int32 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 | */ | ||
1917 | int32 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) | ||
1947 | static 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 | |||
2003 | top: | ||
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 | |||
2113 | LBL_C: pstm_clear(&C); | ||
2114 | LBL_D: pstm_clear(&D); | ||
2115 | LBL_B: pstm_clear(&B); | ||
2116 | LBL_A: pstm_clear(&A); | ||
2117 | LBL_V: pstm_clear(&v); | ||
2118 | LBL_U: pstm_clear(&u); | ||
2119 | LBL_Y: pstm_clear(&y); | ||
2120 | LBL_X: pstm_clear(&x); | ||
2121 | |||
2122 | return res; | ||
2123 | } | ||
2124 | |||
2125 | /* c = 1/a (mod b) for odd b only */ | ||
2126 | int32 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; | ||
2166 | top: | ||
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 | |||
2254 | LBL_D: pstm_clear(&D); | ||
2255 | LBL_B: pstm_clear(&B); | ||
2256 | LBL_V: pstm_clear(&v); | ||
2257 | LBL_U: pstm_clear(&u); | ||
2258 | LBL_Y: pstm_clear(&y); | ||
2259 | LBL_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 | |||
124 | typedef 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 | |||
139 | extern void pstm_set(pstm_int *a, pstm_digit b); | ||
140 | |||
141 | extern void pstm_zero(pstm_int * a); | ||
142 | |||
143 | //bbox: pool unused | ||
144 | #define pstm_init(pool, a) \ | ||
145 | pstm_init( a) | ||
146 | extern 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) | ||
151 | extern 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) | ||
156 | extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, | ||
157 | int16 toSqr); | ||
158 | |||
159 | extern 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) | ||
164 | extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, | ||
165 | uint32 len); | ||
166 | |||
167 | extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c); | ||
168 | |||
169 | extern int32 pstm_unsigned_bin_size(pstm_int *a); | ||
170 | |||
171 | extern int32 pstm_copy(pstm_int * a, pstm_int * b); | ||
172 | |||
173 | extern void pstm_exch(pstm_int * a, pstm_int * b); | ||
174 | |||
175 | extern void pstm_clear(pstm_int * a); | ||
176 | |||
177 | extern 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 | |||
181 | extern int32 pstm_grow(pstm_int * a, int16 size); | ||
182 | |||
183 | extern void pstm_clamp(pstm_int * a); | ||
184 | |||
185 | extern int32 pstm_cmp(pstm_int * a, pstm_int * b); | ||
186 | |||
187 | extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b); | ||
188 | |||
189 | extern void pstm_rshd(pstm_int *a, int16 x); | ||
190 | |||
191 | extern 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) | ||
196 | extern 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) | ||
202 | extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c, | ||
203 | pstm_int *d); | ||
204 | |||
205 | extern int32 pstm_div_2(pstm_int * a, pstm_int * b); | ||
206 | |||
207 | extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); | ||
208 | |||
209 | extern 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) | ||
214 | extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c); | ||
215 | |||
216 | extern 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) | ||
221 | extern 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) | ||
226 | extern 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) | ||
232 | extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, | ||
233 | pstm_int *Y); | ||
234 | |||
235 | extern int32 pstm_2expt(pstm_int *a, int16 b); | ||
236 | |||
237 | extern 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) | ||
242 | extern 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) | ||
248 | extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, | ||
249 | unsigned char *b); | ||
250 | |||
251 | extern 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) | ||
256 | extern 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) | ||
261 | extern 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) | ||
267 | extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, | ||
268 | pstm_digit *paD, uint32 paDlen); | ||
269 | |||
270 | extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b); | ||
271 | |||
272 | extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b); | ||
273 | |||
274 | extern 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) | ||
279 | extern 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 \ | ||
66 | asm( \ | ||
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 \ | ||
79 | asm( \ | ||
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 \ | ||
99 | mu = c[x] * mp | ||
100 | |||
101 | #define INNERMUL \ | ||
102 | asm( \ | ||
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 \ | ||
115 | asm( \ | ||
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 \ | ||
208 | asm( \ | ||
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 \ | ||
223 | mu = c[x] * mp | ||
224 | |||
225 | #ifdef __thumb2__ | ||
226 | //#pragma message ("Using 32 bit ARM Thumb2 Assembly Optimizations") | ||
227 | #define INNERMUL \ | ||
228 | asm( \ | ||
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 \ | ||
240 | asm( \ | ||
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 \ | ||
253 | asm( \ | ||
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 \ | ||
264 | asm( \ | ||
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 \ | ||
284 | mu = c[x] * mp | ||
285 | |||
286 | #define INNERMUL \ | ||
287 | asm( \ | ||
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 \ | ||
305 | asm( \ | ||
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 */ | ||
343 | int32 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) \ | ||
82 | asm( \ | ||
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 \ | ||
103 | c0 = c1 = c2 = 0; | ||
104 | |||
105 | /* forward the carry to the next digit */ | ||
106 | #define COMBA_FORWARD \ | ||
107 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); | ||
108 | |||
109 | /* store the first sum */ | ||
110 | #define COMBA_STORE(x) \ | ||
111 | x = c0; | ||
112 | |||
113 | /* store the second sum [carry] */ | ||
114 | #define COMBA_STORE2(x) \ | ||
115 | x = 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) \ | ||
122 | asm ( \ | ||
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 \ | ||
138 | c0 = c1 = c2 = 0; | ||
139 | |||
140 | #define COMBA_FORWARD \ | ||
141 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); | ||
142 | |||
143 | #define COMBA_STORE(x) \ | ||
144 | x = c0; | ||
145 | |||
146 | #define COMBA_STORE2(x) \ | ||
147 | x = c1; | ||
148 | |||
149 | #define COMBA_FINI | ||
150 | |||
151 | #define MULADD(i, j) \ | ||
152 | asm( \ | ||
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 \ | ||
167 | c0 = c1 = c2 = 0; | ||
168 | |||
169 | #define COMBA_FORWARD \ | ||
170 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); | ||
171 | |||
172 | #define COMBA_STORE(x) \ | ||
173 | x = c0; | ||
174 | |||
175 | #define COMBA_STORE2(x) \ | ||
176 | x = c1; | ||
177 | |||
178 | #define COMBA_FINI | ||
179 | |||
180 | #define MULADD(i, j) \ | ||
181 | asm( \ | ||
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) | ||
228 | static 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 | ||
316 | static 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 | ||
465 | static 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 | |||
756 | int32 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) \ | ||
75 | asm( \ | ||
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) \ | ||
84 | asm( \ | ||
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) \ | ||
96 | asm( \ | ||
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) \ | ||
105 | asm( \ | ||
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 \ | ||
114 | asm( \ | ||
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 \ | ||
134 | c0 = c1 = c2 = 0; | ||
135 | |||
136 | #define COMBA_STORE(x) \ | ||
137 | x = c0; | ||
138 | |||
139 | #define COMBA_STORE2(x) \ | ||
140 | x = c1; | ||
141 | |||
142 | #define CARRY_FORWARD \ | ||
143 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); | ||
144 | |||
145 | #define COMBA_FINI | ||
146 | |||
147 | #define SQRADD(i, j) \ | ||
148 | asm( \ | ||
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) \ | ||
157 | asm( \ | ||
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) \ | ||
169 | asm( \ | ||
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) \ | ||
178 | asm( \ | ||
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 \ | ||
187 | asm( \ | ||
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 \ | ||
204 | c0 = c1 = c2 = 0; | ||
205 | |||
206 | #define COMBA_STORE(x) \ | ||
207 | x = c0; | ||
208 | |||
209 | #define COMBA_STORE2(x) \ | ||
210 | x = c1; | ||
211 | |||
212 | #define CARRY_FORWARD \ | ||
213 | do { 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) \ | ||
219 | asm( \ | ||
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) \ | ||
228 | asm( \ | ||
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) \ | ||
239 | asm( \ | ||
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) \ | ||
245 | asm( \ | ||
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 \ | ||
253 | asm( \ | ||
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 \ | ||
270 | c0 = c1 = c2 = 0; | ||
271 | |||
272 | #define COMBA_STORE(x) \ | ||
273 | x = c0; | ||
274 | |||
275 | #define COMBA_STORE2(x) \ | ||
276 | x = c1; | ||
277 | |||
278 | #define CARRY_FORWARD \ | ||
279 | do { 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) \ | ||
285 | asm( \ | ||
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) \ | ||
301 | asm( \ | ||
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) \ | ||
326 | asm( \ | ||
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) \ | ||
334 | asm( \ | ||
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 \ | ||
349 | asm( \ | ||
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) | ||
445 | static 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 | ||
554 | static 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 | ||
740 | static 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 | */ | ||
1086 | int32 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) | ||
16 | static //bbox | ||
17 | int32 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) | ||
61 | static //bbox | ||
62 | int32 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; | ||
172 | error: | ||
173 | res = PS_FAILURE; | ||
174 | done: | ||
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 | |||
182 | int32 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 | |||
9 | typedef 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) | ||
18 | int32 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 | |||
28 | static 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 | |||
44 | static 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) { \ | ||
94 | x = ((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) { \ | ||
112 | x = (((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) { \ | ||
126 | x = ((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) { \ | ||
144 | x = (((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) { \ | ||
161 | x = ((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) { \ | ||
179 | x = (((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) { \ | ||
186 | unsigned 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) { \ | ||
203 | x = (((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) { \ | ||
234 | x = ((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) { \ | ||
252 | x = (((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) { \ | ||
276 | x = (((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 | ||
359 | typedef struct { | ||
360 | uint32 eK[64], dK[64]; | ||
361 | int32 Nr; | ||
362 | } psAesKey_t; | ||
363 | |||
364 | typedef 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 | |||
405 | typedef struct { | ||
406 | uint16 key_schedule[52]; | ||
407 | } psIdeaKey_t; | ||
408 | |||
409 | typedef 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 | |||
425 | typedef struct { | ||
426 | uint32 K[32], dK[32]; | ||
427 | } psSeedKey_t; | ||
428 | |||
429 | typedef 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 | |||
445 | typedef struct { | ||
446 | uint32 ek[3][32], dk[3][32]; | ||
447 | } psDes3Key_t; | ||
448 | |||
449 | /* | ||
450 | A block cipher CBC structure | ||
451 | */ | ||
452 | typedef 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 | ||
463 | typedef 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 | ||
472 | typedef struct { | ||
473 | unsigned xkey[64]; | ||
474 | } psRc2Key_t; | ||
475 | |||
476 | typedef 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 | |||
487 | typedef 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 | ||
125 | config FEATURE_UDHCP_RFC3397 | 125 | config 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 | ||
134 | config FEATURE_UDHCP_8021Q | 134 | config 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 | |||
144 | struct host_info { | 169 | struct 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 | }; |
152 | static const char P_FTP[] ALIGN1 = "ftp"; | 177 | static const char P_FTP[] ALIGN1 = "ftp"; |
153 | static const char P_HTTP[] ALIGN1 = "http"; | 178 | static const char P_HTTP[] ALIGN1 = "http"; |
154 | #if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER | 179 | #if SSL_SUPPORTED |
155 | static const char P_HTTPS[] ALIGN1 = "https"; | 180 | static const char P_HTTPS[] ALIGN1 = "https"; |
156 | #endif | 181 | #endif |
157 | 182 | ||
@@ -232,16 +257,17 @@ struct globals { | |||
232 | enum { | 257 | enum { |
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 | ||
247 | enum { | 273 | enum { |
@@ -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' */ |
398 | static char fgets_and_trim(FILE *fp) | 424 | static 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 | 769 | static void spawn_ssl_client(const char *host, int network_fd) |
738 | static 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: |