diff options
Diffstat (limited to 'networking')
-rw-r--r-- | networking/Config.src | 3 | ||||
-rw-r--r-- | networking/ftpd.c | 39 | ||||
-rw-r--r-- | networking/hostname.c | 4 | ||||
-rw-r--r-- | networking/httpd.c | 2 | ||||
-rw-r--r-- | networking/libiproute/iproute.c | 16 | ||||
-rw-r--r-- | networking/ntpd.c | 6 | ||||
-rw-r--r-- | networking/telnetd.c | 4 | ||||
-rw-r--r-- | networking/tftp.c | 2 | ||||
-rw-r--r-- | networking/tls.c | 906 | ||||
-rw-r--r-- | networking/tls.h | 6 | ||||
-rw-r--r-- | networking/tls_aesgcm.c | 5 |
11 files changed, 358 insertions, 635 deletions
diff --git a/networking/Config.src b/networking/Config.src index d5fc9d377..aa0806a18 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -84,7 +84,7 @@ config FEATURE_TLS_INTERNAL | |||
84 | 84 | ||
85 | config FEATURE_TLS_SCHANNEL | 85 | config FEATURE_TLS_SCHANNEL |
86 | bool "Schannel SSP" | 86 | bool "Schannel SSP" |
87 | depends on TLS | 87 | depends on TLS && PLATFORM_MINGW32 |
88 | help | 88 | help |
89 | Use the Schannel SSP to provide TLS support. | 89 | Use the Schannel SSP to provide TLS support. |
90 | Reduces code size and enables certificate checking. | 90 | Reduces code size and enables certificate checking. |
@@ -113,7 +113,6 @@ config FEATURE_TLS_SCHANNEL_1_3 | |||
113 | 113 | ||
114 | INSERT | 114 | INSERT |
115 | 115 | ||
116 | |||
117 | source networking/udhcp/Config.in | 116 | source networking/udhcp/Config.in |
118 | 117 | ||
119 | config IFUPDOWN_UDHCPC_CMD_OPTIONS | 118 | config IFUPDOWN_UDHCPC_CMD_OPTIONS |
diff --git a/networking/ftpd.c b/networking/ftpd.c index 0d6a289c7..c3125410e 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c | |||
@@ -190,54 +190,39 @@ struct globals { | |||
190 | } while (0) | 190 | } while (0) |
191 | 191 | ||
192 | 192 | ||
193 | /* escape_text("pfx:", str, (0xff << 8) + '\r') | ||
194 | * Duplicate 0xff, append \r ^^^^^^^^^^^^^^^^^^ | ||
195 | */ | ||
193 | static char * | 196 | static char * |
194 | escape_text(const char *prepend, const char *str, unsigned escapee) | 197 | escape_text(const char *prepend, const char *str, unsigned escapee) |
195 | { | 198 | { |
196 | unsigned retlen, remainlen, chunklen; | 199 | char *ret, *p; |
197 | char *ret, *found; | ||
198 | char append; | 200 | char append; |
199 | 201 | ||
200 | append = (char)escapee; | 202 | append = (char)escapee; |
201 | escapee >>= 8; | 203 | escapee >>= 8; |
202 | 204 | ||
203 | remainlen = strlen(str); | 205 | ret = xmalloc(strlen(prepend) + strlen(str) * 2 + 1 + 1); |
204 | retlen = strlen(prepend); | 206 | p = stpcpy(ret, prepend); |
205 | ret = xmalloc(retlen + remainlen * 2 + 1 + 1); | ||
206 | strcpy(ret, prepend); | ||
207 | 207 | ||
208 | for (;;) { | 208 | for (;;) { |
209 | found = strchrnul(str, escapee); | 209 | char *found = strchrnul(str, escapee); |
210 | chunklen = found - str + 1; | ||
211 | 210 | ||
212 | /* Copy chunk up to and including escapee (or NUL) to ret */ | 211 | /* Copy up to and including escapee (or NUL) */ |
213 | memcpy(ret + retlen, str, chunklen); | 212 | p = mempcpy(p, str, found - str + 1); |
214 | retlen += chunklen; | ||
215 | 213 | ||
216 | if (*found == '\0') { | 214 | if (*found == '\0') { |
217 | /* It wasn't escapee, it was NUL! */ | 215 | /* It wasn't escapee, it was NUL! */ |
218 | ret[retlen - 1] = append; /* replace NUL */ | ||
219 | ret[retlen] = '\0'; /* add NUL */ | ||
220 | break; | 216 | break; |
221 | } | 217 | } |
222 | ret[retlen++] = escapee; /* duplicate escapee */ | ||
223 | str = found + 1; | 218 | str = found + 1; |
219 | *p++ = escapee; /* duplicate escapee */ | ||
224 | } | 220 | } |
221 | p[-1] = append; /* replace NUL */ | ||
222 | *p = '\0'; /* add NUL */ | ||
225 | return ret; | 223 | return ret; |
226 | } | 224 | } |
227 | 225 | ||
228 | /* Returns strlen as a bonus */ | ||
229 | static unsigned | ||
230 | replace_char(char *str, char from, char to) | ||
231 | { | ||
232 | char *p = str; | ||
233 | while (*p) { | ||
234 | if (*p == from) | ||
235 | *p = to; | ||
236 | p++; | ||
237 | } | ||
238 | return p - str; | ||
239 | } | ||
240 | |||
241 | static void | 226 | static void |
242 | verbose_log(const char *str) | 227 | verbose_log(const char *str) |
243 | { | 228 | { |
diff --git a/networking/hostname.c b/networking/hostname.c index 36cb70866..101b89e77 100644 --- a/networking/hostname.c +++ b/networking/hostname.c | |||
@@ -25,8 +25,8 @@ | |||
25 | //applet:IF_DNSDOMAINNAME(APPLET_NOEXEC(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname)) | 25 | //applet:IF_DNSDOMAINNAME(APPLET_NOEXEC(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname)) |
26 | //applet:IF_HOSTNAME( APPLET_NOEXEC(hostname, hostname, BB_DIR_BIN, BB_SUID_DROP, hostname )) | 26 | //applet:IF_HOSTNAME( APPLET_NOEXEC(hostname, hostname, BB_DIR_BIN, BB_SUID_DROP, hostname )) |
27 | 27 | ||
28 | //kbuild: lib-$(CONFIG_HOSTNAME) += hostname.o | 28 | //kbuild:lib-$(CONFIG_HOSTNAME) += hostname.o |
29 | //kbuild: lib-$(CONFIG_DNSDOMAINNAME) += hostname.o | 29 | //kbuild:lib-$(CONFIG_DNSDOMAINNAME) += hostname.o |
30 | 30 | ||
31 | //usage:#define hostname_trivial_usage | 31 | //usage:#define hostname_trivial_usage |
32 | //usage: "[-sidf] [HOSTNAME | -F FILE]" | 32 | //usage: "[-sidf] [HOSTNAME | -F FILE]" |
diff --git a/networking/httpd.c b/networking/httpd.c index 1dae602ee..50595104c 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -3074,7 +3074,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
3074 | salt[0] = '$'; | 3074 | salt[0] = '$'; |
3075 | salt[1] = '1'; | 3075 | salt[1] = '1'; |
3076 | salt[2] = '$'; | 3076 | salt[2] = '$'; |
3077 | crypt_make_salt(salt + 3, 4); | 3077 | crypt_make_rand64encoded(salt + 3, 8 / 2); /* 8 chars */ |
3078 | puts(pw_encrypt(pass, salt, /*cleanup:*/ 0)); | 3078 | puts(pw_encrypt(pass, salt, /*cleanup:*/ 0)); |
3079 | return 0; | 3079 | return 0; |
3080 | } | 3080 | } |
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index cd77f642f..a30f070eb 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -302,24 +302,22 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, | |||
302 | printf("notify "); | 302 | printf("notify "); |
303 | } | 303 | } |
304 | 304 | ||
305 | if (r->rtm_family == AF_INET6) { | 305 | if (r->rtm_family == AF_INET || r->rtm_family == AF_INET6) { |
306 | struct rta_cacheinfo *ci = NULL; | 306 | if (r->rtm_family == AF_INET) { |
307 | if (tb[RTA_CACHEINFO]) { | ||
308 | ci = RTA_DATA(tb[RTA_CACHEINFO]); | ||
309 | } | ||
310 | if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) { | ||
311 | if (r->rtm_flags & RTM_F_CLONED) { | 307 | if (r->rtm_flags & RTM_F_CLONED) { |
312 | printf("%c cache ", _SL_); | 308 | printf("%c cache ", _SL_); |
309 | /* upstream: print_cache_flags() prints more here */ | ||
313 | } | 310 | } |
311 | } | ||
312 | if (tb[RTA_CACHEINFO]) { | ||
313 | struct rta_cacheinfo *ci = RTA_DATA(tb[RTA_CACHEINFO]); | ||
314 | if (ci->rta_expires) { | 314 | if (ci->rta_expires) { |
315 | printf(" expires %dsec", ci->rta_expires / get_hz()); | 315 | printf(" expires %dsec", ci->rta_expires / get_hz()); |
316 | } | 316 | } |
317 | if (ci->rta_error != 0) { | 317 | if (ci->rta_error != 0) { |
318 | printf(" error %d", ci->rta_error); | 318 | printf(" error %d", ci->rta_error); |
319 | } | 319 | } |
320 | } else if (ci) { | 320 | /* upstream: print_rta_cacheinfo() prints more here */ |
321 | if (ci->rta_error != 0) | ||
322 | printf(" error %d", ci->rta_error); | ||
323 | } | 321 | } |
324 | } | 322 | } |
325 | if (tb[RTA_IIF] && G_filter.iif == 0) { | 323 | if (tb[RTA_IIF] && G_filter.iif == 0) { |
diff --git a/networking/ntpd.c b/networking/ntpd.c index dcbdb8e60..dd0a9c91f 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -205,7 +205,7 @@ | |||
205 | #define MINDISP 0.01 /* minimum dispersion (sec) */ | 205 | #define MINDISP 0.01 /* minimum dispersion (sec) */ |
206 | #define MAXDISP 16 /* maximum dispersion (sec) */ | 206 | #define MAXDISP 16 /* maximum dispersion (sec) */ |
207 | #define MAXSTRAT 16 /* maximum stratum (infinity metric) */ | 207 | #define MAXSTRAT 16 /* maximum stratum (infinity metric) */ |
208 | #define MAXDIST 1 /* distance threshold (sec) */ | 208 | #define MAXDIST 3 /* distance threshold (sec): do not use peers who are farther away */ |
209 | #define MIN_SELECTED 1 /* minimum intersection survivors */ | 209 | #define MIN_SELECTED 1 /* minimum intersection survivors */ |
210 | #define MIN_CLUSTERED 3 /* minimum cluster survivors */ | 210 | #define MIN_CLUSTERED 3 /* minimum cluster survivors */ |
211 | 211 | ||
@@ -1057,7 +1057,7 @@ step_time(double offset) | |||
1057 | } | 1057 | } |
1058 | tval = tvn.tv_sec; | 1058 | tval = tvn.tv_sec; |
1059 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); | 1059 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); |
1060 | bb_info_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); | 1060 | bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); |
1061 | //maybe? G.FREQHOLD_cnt = 0; | 1061 | //maybe? G.FREQHOLD_cnt = 0; |
1062 | 1062 | ||
1063 | /* Correct various fields which contain time-relative values: */ | 1063 | /* Correct various fields which contain time-relative values: */ |
@@ -1976,7 +1976,7 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1976 | 1976 | ||
1977 | p->reachable_bits |= 1; | 1977 | p->reachable_bits |= 1; |
1978 | if ((MAX_VERBOSE && G.verbose) || (option_mask32 & OPT_w)) { | 1978 | if ((MAX_VERBOSE && G.verbose) || (option_mask32 & OPT_w)) { |
1979 | bb_info_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x", | 1979 | bb_error_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x", |
1980 | p->p_dotted, | 1980 | p->p_dotted, |
1981 | offset, | 1981 | offset, |
1982 | p->p_raw_delay, | 1982 | p->p_raw_delay, |
diff --git a/networking/telnetd.c b/networking/telnetd.c index bfeea1400..a5a783047 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -104,8 +104,8 @@ | |||
104 | //usage:#define telnetd_full_usage "\n\n" | 104 | //usage:#define telnetd_full_usage "\n\n" |
105 | //usage: "Handle incoming telnet connections" | 105 | //usage: "Handle incoming telnet connections" |
106 | //usage: IF_NOT_FEATURE_TELNETD_STANDALONE(" via inetd") "\n" | 106 | //usage: IF_NOT_FEATURE_TELNETD_STANDALONE(" via inetd") "\n" |
107 | //usage: "\n -l LOGIN Exec LOGIN on connect" | 107 | //usage: "\n -l LOGIN Exec LOGIN on connect (default /bin/login)" |
108 | //usage: "\n -f ISSUE_FILE Display ISSUE_FILE instead of /etc/issue" | 108 | //usage: "\n -f ISSUE_FILE Display ISSUE_FILE instead of /etc/issue.net" |
109 | //usage: "\n -K Close connection as soon as login exits" | 109 | //usage: "\n -K Close connection as soon as login exits" |
110 | //usage: "\n (normally wait until all programs close slave pty)" | 110 | //usage: "\n (normally wait until all programs close slave pty)" |
111 | //usage: IF_FEATURE_TELNETD_STANDALONE( | 111 | //usage: IF_FEATURE_TELNETD_STANDALONE( |
diff --git a/networking/tftp.c b/networking/tftp.c index f5b4367ca..b698a9288 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -250,7 +250,7 @@ static int tftp_blksize_check(const char *blksize_str, int maxsize) | |||
250 | return -1; | 250 | return -1; |
251 | } | 251 | } |
252 | # if ENABLE_TFTP_DEBUG | 252 | # if ENABLE_TFTP_DEBUG |
253 | bb_info_msg("using blksize %u", blksize); | 253 | bb_error_msg("using blksize %u", blksize); |
254 | # endif | 254 | # endif |
255 | return blksize; | 255 | return blksize; |
256 | } | 256 | } |
diff --git a/networking/tls.c b/networking/tls.c index b048d6eeb..c099d056f 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -22,19 +22,7 @@ | |||
22 | 22 | ||
23 | #include "tls.h" | 23 | #include "tls.h" |
24 | 24 | ||
25 | #if ENABLE_FEATURE_TLS_SCHANNEL || ENABLE_FEATURE_USE_CNG_API | ||
26 | #include <windows.h> | ||
27 | #endif | ||
28 | |||
29 | #if !ENABLE_FEATURE_TLS_SCHANNEL | 25 | #if !ENABLE_FEATURE_TLS_SCHANNEL |
30 | #if ENABLE_FEATURE_USE_CNG_API | ||
31 | # include <bcrypt.h> | ||
32 | |||
33 | // these work on Windows >= 10 | ||
34 | # define BCRYPT_HMAC_SHA1_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000a1) | ||
35 | # define BCRYPT_HMAC_SHA256_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000b1) | ||
36 | #endif | ||
37 | |||
38 | // Usually enabled. You can disable some of them to force only | 26 | // Usually enabled. You can disable some of them to force only |
39 | // specific ciphers to be advertized to server. | 27 | // specific ciphers to be advertized to server. |
40 | // (this would not exclude code to handle disabled ciphers, no code size win) | 28 | // (this would not exclude code to handle disabled ciphers, no code size win) |
@@ -201,8 +189,6 @@ | |||
201 | #define TLS_MAX_OUTBUF (1 << 14) | 189 | #define TLS_MAX_OUTBUF (1 << 14) |
202 | 190 | ||
203 | enum { | 191 | enum { |
204 | SHA_INSIZE = 64, | ||
205 | |||
206 | AES128_KEYSIZE = 16, | 192 | AES128_KEYSIZE = 16, |
207 | AES256_KEYSIZE = 32, | 193 | AES256_KEYSIZE = 32, |
208 | 194 | ||
@@ -348,34 +334,6 @@ void FAST_FUNC tls_get_random(void *buf, unsigned len) | |||
348 | xfunc_die(); | 334 | xfunc_die(); |
349 | } | 335 | } |
350 | 336 | ||
351 | static void xorbuf3(void *dst, const void *src1, const void *src2, unsigned count) | ||
352 | { | ||
353 | uint8_t *d = dst; | ||
354 | const uint8_t *s1 = src1; | ||
355 | const uint8_t* s2 = src2; | ||
356 | while (count--) | ||
357 | *d++ = *s1++ ^ *s2++; | ||
358 | } | ||
359 | |||
360 | void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count) | ||
361 | { | ||
362 | xorbuf3(dst, dst, src, count); | ||
363 | } | ||
364 | |||
365 | void FAST_FUNC xorbuf_aligned_AES_BLOCK_SIZE(void *dst, const void *src) | ||
366 | { | ||
367 | unsigned long *d = dst; | ||
368 | const unsigned long *s = src; | ||
369 | d[0] ^= s[0]; | ||
370 | #if ULONG_MAX <= 0xffffffffffffffff | ||
371 | d[1] ^= s[1]; | ||
372 | #if ULONG_MAX == 0xffffffff | ||
373 | d[2] ^= s[2]; | ||
374 | d[3] ^= s[3]; | ||
375 | #endif | ||
376 | #endif | ||
377 | } | ||
378 | |||
379 | #if !TLS_DEBUG_HASH | 337 | #if !TLS_DEBUG_HASH |
380 | # define hash_handshake(tls, fmt, buffer, len) \ | 338 | # define hash_handshake(tls, fmt, buffer, len) \ |
381 | hash_handshake(tls, buffer, len) | 339 | hash_handshake(tls, buffer, len) |
@@ -406,191 +364,6 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer | |||
406 | # define TLS_MAC_SIZE(tls) (tls)->MAC_size | 364 | # define TLS_MAC_SIZE(tls) (tls)->MAC_size |
407 | #endif | 365 | #endif |
408 | 366 | ||
409 | // RFC 2104: | ||
410 | // HMAC(key, text) based on a hash H (say, sha256) is: | ||
411 | // ipad = [0x36 x INSIZE] | ||
412 | // opad = [0x5c x INSIZE] | ||
413 | // HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text)) | ||
414 | // | ||
415 | // H(key XOR opad) and H(key XOR ipad) can be precomputed | ||
416 | // if we often need HMAC hmac with the same key. | ||
417 | // | ||
418 | // text is often given in disjoint pieces. | ||
419 | #if !ENABLE_FEATURE_USE_CNG_API | ||
420 | typedef struct hmac_precomputed { | ||
421 | md5sha_ctx_t hashed_key_xor_ipad; | ||
422 | md5sha_ctx_t hashed_key_xor_opad; | ||
423 | } hmac_precomputed_t; | ||
424 | |||
425 | typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; | ||
426 | |||
427 | #define sha1_begin_hmac sha1_begin | ||
428 | #define sha256_begin_hmac sha256_begin | ||
429 | #define hmac_uninit(...) ((void)0) | ||
430 | |||
431 | #if !ENABLE_FEATURE_TLS_SHA1 | ||
432 | #define hmac_begin(pre,key,key_size,begin) \ | ||
433 | hmac_begin(pre,key,key_size) | ||
434 | #define begin sha256_begin | ||
435 | #endif | ||
436 | |||
437 | static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin) | ||
438 | { | ||
439 | uint8_t key_xor_ipad[SHA_INSIZE]; | ||
440 | uint8_t key_xor_opad[SHA_INSIZE]; | ||
441 | // uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE]; | ||
442 | unsigned i; | ||
443 | |||
444 | // "The authentication key can be of any length up to INSIZE, the | ||
445 | // block length of the hash function. Applications that use keys longer | ||
446 | // than INSIZE bytes will first hash the key using H and then use the | ||
447 | // resultant OUTSIZE byte string as the actual key to HMAC." | ||
448 | if (key_size > SHA_INSIZE) { | ||
449 | bb_simple_error_msg_and_die("HMAC key>64"); //does not happen (yet?) | ||
450 | // md5sha_ctx_t ctx; | ||
451 | // begin(&ctx); | ||
452 | // md5sha_hash(&ctx, key, key_size); | ||
453 | // key_size = sha_end(&ctx, tempkey); | ||
454 | // //key = tempkey; - right? RIGHT? why does it work without this? | ||
455 | // // because SHA_INSIZE is 64, but hmac() is always called with | ||
456 | // // key_size = tls->MAC_size = SHA1/256_OUTSIZE (20 or 32), | ||
457 | // // and prf_hmac_sha256() -> hmac_sha256() key sizes are: | ||
458 | // // - RSA_PREMASTER_SIZE is 48 | ||
459 | // // - CURVE25519_KEYSIZE is 32 | ||
460 | // // - master_secret[] is 48 | ||
461 | } | ||
462 | |||
463 | for (i = 0; i < key_size; i++) { | ||
464 | key_xor_ipad[i] = key[i] ^ 0x36; | ||
465 | key_xor_opad[i] = key[i] ^ 0x5c; | ||
466 | } | ||
467 | for (; i < SHA_INSIZE; i++) { | ||
468 | key_xor_ipad[i] = 0x36; | ||
469 | key_xor_opad[i] = 0x5c; | ||
470 | } | ||
471 | |||
472 | begin(&pre->hashed_key_xor_ipad); | ||
473 | begin(&pre->hashed_key_xor_opad); | ||
474 | md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); | ||
475 | md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); | ||
476 | } | ||
477 | #undef begin | ||
478 | |||
479 | static unsigned hmac_sha_precomputed_v( | ||
480 | hmac_precomputed_t *pre, | ||
481 | uint8_t *out, | ||
482 | va_list va) | ||
483 | { | ||
484 | uint8_t *text; | ||
485 | unsigned len; | ||
486 | |||
487 | /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ | ||
488 | /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ | ||
489 | |||
490 | /* calculate out = H((key XOR ipad) + text) */ | ||
491 | while ((text = va_arg(va, uint8_t*)) != NULL) { | ||
492 | unsigned text_size = va_arg(va, unsigned); | ||
493 | md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size); | ||
494 | } | ||
495 | len = sha_end(&pre->hashed_key_xor_ipad, out); | ||
496 | |||
497 | /* out = H((key XOR opad) + out) */ | ||
498 | md5sha_hash(&pre->hashed_key_xor_opad, out, len); | ||
499 | return sha_end(&pre->hashed_key_xor_opad, out); | ||
500 | } | ||
501 | #else | ||
502 | #define sha1_begin_hmac BCRYPT_HMAC_SHA1_ALG_HANDLE | ||
503 | #define sha256_begin_hmac BCRYPT_HMAC_SHA256_ALG_HANDLE | ||
504 | |||
505 | #if !ENABLE_FEATURE_TLS_SHA1 | ||
506 | #define hmac_begin(pre,key,key_size,begin) _hmac_begin(pre, key, key_size, sha256_begin_hmac) | ||
507 | #else | ||
508 | #define hmac_begin _hmac_begin | ||
509 | #endif | ||
510 | |||
511 | typedef struct bcrypt_hash_ctx_t hmac_precomputed_t; | ||
512 | |||
513 | static void _hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, BCRYPT_ALG_HANDLE alg_handle) { | ||
514 | DWORD hash_object_length = 0; | ||
515 | ULONG _unused; | ||
516 | NTSTATUS status; | ||
517 | |||
518 | status = BCryptGetProperty(alg_handle, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hash_object_length, sizeof(DWORD), &_unused, 0); | ||
519 | mingw_die_if_error(status, "BCryptGetProperty"); | ||
520 | status = BCryptGetProperty(alg_handle, BCRYPT_HASH_LENGTH, (PUCHAR)&pre->output_size, sizeof(DWORD), &_unused, 0); | ||
521 | mingw_die_if_error(status, "BCryptGetProperty"); | ||
522 | |||
523 | |||
524 | pre->hash_obj = xmalloc(hash_object_length); | ||
525 | |||
526 | status = BCryptCreateHash(alg_handle, &pre->handle, pre->hash_obj, hash_object_length, key, key_size, BCRYPT_HASH_REUSABLE_FLAG); | ||
527 | mingw_die_if_error(status, "BCryptCreateHash"); | ||
528 | } | ||
529 | |||
530 | static unsigned hmac_sha_precomputed_v( | ||
531 | hmac_precomputed_t *pre, | ||
532 | uint8_t *out, | ||
533 | va_list va) | ||
534 | { | ||
535 | uint8_t *text; | ||
536 | NTSTATUS status; | ||
537 | |||
538 | while ((text = va_arg(va, uint8_t*)) != NULL) { | ||
539 | unsigned text_size = va_arg(va, unsigned); | ||
540 | /*status = */ BCryptHashData(pre->handle, text, text_size, 0); | ||
541 | //mingw_die_if_error(status, "BCryptHashData"); | ||
542 | } | ||
543 | |||
544 | status = BCryptFinishHash(pre->handle, out, pre->output_size, 0); | ||
545 | mingw_die_if_error(status, "BCryptFinishHash"); | ||
546 | |||
547 | return pre->output_size; | ||
548 | } | ||
549 | |||
550 | static void hmac_uninit(hmac_precomputed_t *pre) { | ||
551 | BCryptDestroyHash(pre->handle); | ||
552 | free(pre->hash_obj); | ||
553 | } | ||
554 | |||
555 | #endif | ||
556 | |||
557 | static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out, ...) | ||
558 | { | ||
559 | hmac_precomputed_t pre; | ||
560 | va_list va; | ||
561 | unsigned len; | ||
562 | |||
563 | va_start(va, out); | ||
564 | pre = *pre_init; /* struct copy */ | ||
565 | len = hmac_sha_precomputed_v(&pre, out, va); | ||
566 | va_end(va); | ||
567 | return len; | ||
568 | } | ||
569 | |||
570 | #if !ENABLE_FEATURE_TLS_SHA1 | ||
571 | #define hmac(tls,out,key,key_size,...) \ | ||
572 | hmac(out,key,key_size, __VA_ARGS__) | ||
573 | #endif | ||
574 | static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) | ||
575 | { | ||
576 | hmac_precomputed_t pre; | ||
577 | va_list va; | ||
578 | unsigned len; | ||
579 | |||
580 | va_start(va, key_size); | ||
581 | |||
582 | hmac_begin(&pre, key, key_size, | ||
583 | (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE) | ||
584 | ? sha1_begin_hmac | ||
585 | : sha256_begin_hmac | ||
586 | ); | ||
587 | len = hmac_sha_precomputed_v(&pre, out, va); | ||
588 | |||
589 | va_end(va); | ||
590 | hmac_uninit(&pre); | ||
591 | return len; | ||
592 | } | ||
593 | |||
594 | // RFC 5246: | 367 | // RFC 5246: |
595 | // 5. HMAC and the Pseudorandom Function | 368 | // 5. HMAC and the Pseudorandom Function |
596 | //... | 369 | //... |
@@ -635,7 +408,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/ | |||
635 | const char *label, | 408 | const char *label, |
636 | uint8_t *seed, unsigned seed_size) | 409 | uint8_t *seed, unsigned seed_size) |
637 | { | 410 | { |
638 | hmac_precomputed_t pre; | 411 | hmac_ctx_t ctx; |
639 | uint8_t a[TLS_MAX_MAC_SIZE]; | 412 | uint8_t a[TLS_MAX_MAC_SIZE]; |
640 | uint8_t *out_p = outbuf; | 413 | uint8_t *out_p = outbuf; |
641 | unsigned label_size = strlen(label); | 414 | unsigned label_size = strlen(label); |
@@ -645,29 +418,28 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/ | |||
645 | #define SEED label, label_size, seed, seed_size | 418 | #define SEED label, label_size, seed, seed_size |
646 | #define A a, MAC_size | 419 | #define A a, MAC_size |
647 | 420 | ||
648 | hmac_begin(&pre, secret, secret_size, sha256_begin_hmac); | 421 | hmac_begin(&ctx, secret, secret_size, sha256_begin_hmac); |
649 | 422 | ||
650 | /* A(1) = HMAC_hash(secret, seed) */ | 423 | /* A(1) = HMAC_hash(secret, seed) */ |
651 | hmac_sha_precomputed(&pre, a, SEED, NULL); | 424 | hmac_peek_hash(&ctx, a, SEED, NULL); |
652 | 425 | ||
653 | for (;;) { | 426 | for (;;) { |
654 | /* HMAC_hash(secret, A(1) + seed) */ | 427 | /* HMAC_hash(secret, A(1) + seed) */ |
655 | if (outbuf_size <= MAC_size) { | 428 | if (outbuf_size <= MAC_size) { |
656 | /* Last, possibly incomplete, block */ | 429 | /* Last, possibly incomplete, block */ |
657 | /* (use a[] as temp buffer) */ | 430 | /* (use a[] as temp buffer) */ |
658 | hmac_sha_precomputed(&pre, a, A, SEED, NULL); | 431 | hmac_peek_hash(&ctx, a, A, SEED, NULL); |
659 | memcpy(out_p, a, outbuf_size); | 432 | memcpy(out_p, a, outbuf_size); |
433 | hmac_uninit(&ctx); | ||
660 | return; | 434 | return; |
661 | } | 435 | } |
662 | /* Not last block. Store directly to result buffer */ | 436 | /* Not last block. Store directly to result buffer */ |
663 | hmac_sha_precomputed(&pre, out_p, A, SEED, NULL); | 437 | hmac_peek_hash(&ctx, out_p, A, SEED, NULL); |
664 | out_p += MAC_size; | 438 | out_p += MAC_size; |
665 | outbuf_size -= MAC_size; | 439 | outbuf_size -= MAC_size; |
666 | /* A(2) = HMAC_hash(secret, A(1)) */ | 440 | /* A(2) = HMAC_hash(secret, A(1)) */ |
667 | hmac_sha_precomputed(&pre, a, A, NULL); | 441 | hmac_peek_hash(&ctx, a, A, NULL); |
668 | } | 442 | } |
669 | |||
670 | hmac_uninit(&pre); | ||
671 | #undef A | 443 | #undef A |
672 | #undef SECRET | 444 | #undef SECRET |
673 | #undef SEED | 445 | #undef SEED |
@@ -733,6 +505,32 @@ static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len) | |||
733 | return record; | 505 | return record; |
734 | } | 506 | } |
735 | 507 | ||
508 | /* Calculate the HMAC over the list of blocks */ | ||
509 | #if !ENABLE_FEATURE_TLS_SHA1 | ||
510 | #define hmac_blocks(tls,out,key,key_size,...) \ | ||
511 | hmac_blocks(out,key,key_size, __VA_ARGS__) | ||
512 | #endif | ||
513 | static unsigned hmac_blocks(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) | ||
514 | { | ||
515 | hmac_ctx_t ctx; | ||
516 | va_list va; | ||
517 | unsigned len; | ||
518 | |||
519 | hmac_begin(&ctx, key, key_size, | ||
520 | (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE) | ||
521 | ? sha1_begin_hmac | ||
522 | : sha256_begin_hmac | ||
523 | ); | ||
524 | |||
525 | va_start(va, key_size); | ||
526 | hmac_hash_v(&ctx, va); | ||
527 | va_end(va); | ||
528 | |||
529 | len = hmac_end(&ctx, out); | ||
530 | hmac_uninit(&ctx); | ||
531 | return len; | ||
532 | } | ||
533 | |||
736 | static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) | 534 | static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) |
737 | { | 535 | { |
738 | uint8_t *buf = tls->outbuf + OUTBUF_PFX; | 536 | uint8_t *buf = tls->outbuf + OUTBUF_PFX; |
@@ -754,7 +552,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un | |||
754 | xhdr->len16_lo = size & 0xff; | 552 | xhdr->len16_lo = size & 0xff; |
755 | 553 | ||
756 | /* Calculate MAC signature */ | 554 | /* Calculate MAC signature */ |
757 | hmac(tls, buf + size, /* result */ | 555 | hmac_blocks(tls, buf + size, /* result */ |
758 | tls->client_write_MAC_key, TLS_MAC_SIZE(tls), | 556 | tls->client_write_MAC_key, TLS_MAC_SIZE(tls), |
759 | &tls->write_seq64_be, sizeof(tls->write_seq64_be), | 557 | &tls->write_seq64_be, sizeof(tls->write_seq64_be), |
760 | xhdr, RECHDR_LEN, | 558 | xhdr, RECHDR_LEN, |
@@ -943,8 +741,13 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty | |||
943 | cnt++; | 741 | cnt++; |
944 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ | 742 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ |
945 | aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); | 743 | aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); |
946 | n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; | 744 | if (remaining >= AES_BLOCK_SIZE) { |
947 | xorbuf(buf, scratch, n); | 745 | n = AES_BLOCK_SIZE; |
746 | xorbuf_AES_BLOCK_SIZE(buf, scratch); | ||
747 | } else { | ||
748 | n = remaining; | ||
749 | xorbuf(buf, scratch, n); | ||
750 | } | ||
948 | buf += n; | 751 | buf += n; |
949 | remaining -= n; | 752 | remaining -= n; |
950 | } | 753 | } |
@@ -1102,7 +905,7 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) | |||
1102 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ | 905 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ |
1103 | aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); | 906 | aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); |
1104 | n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; | 907 | n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; |
1105 | xorbuf3(buf, scratch, buf + 8, n); | 908 | xorbuf_3(buf, scratch, buf + 8, n); |
1106 | buf += n; | 909 | buf += n; |
1107 | remaining -= n; | 910 | remaining -= n; |
1108 | } | 911 | } |
@@ -2560,6 +2363,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) | |||
2560 | } | 2363 | } |
2561 | } | 2364 | } |
2562 | #else | 2365 | #else |
2366 | #include <stdbool.h> | ||
2563 | 2367 | ||
2564 | #if ENABLE_FEATURE_TLS_SCHANNEL_1_3 | 2368 | #if ENABLE_FEATURE_TLS_SCHANNEL_1_3 |
2565 | #include <subauth.h> | 2369 | #include <subauth.h> |
@@ -2575,6 +2379,8 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) | |||
2575 | (ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_REPLAY_DETECT | \ | 2379 | (ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_REPLAY_DETECT | \ |
2576 | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS) | 2380 | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS) |
2577 | 2381 | ||
2382 | #define SEC_STATUS_FAIL(status) ((status) != SEC_E_OK) | ||
2383 | |||
2578 | static char *hresult_to_error_string(HRESULT result) { | 2384 | static char *hresult_to_error_string(HRESULT result) { |
2579 | char *output = NULL; | 2385 | char *output = NULL; |
2580 | 2386 | ||
@@ -2586,234 +2392,210 @@ static char *hresult_to_error_string(HRESULT result) { | |||
2586 | return output; | 2392 | return output; |
2587 | } | 2393 | } |
2588 | 2394 | ||
2589 | static ssize_t tls_read(struct tls_state *state, char *buf, ssize_t len) { | 2395 | static void init_sec_buffer(SecBuffer *buffer, void *pvBuffer, unsigned long cbBuffer, unsigned long BufferType) { |
2396 | buffer->BufferType = BufferType; | ||
2397 | buffer->cbBuffer = cbBuffer; | ||
2398 | buffer->pvBuffer = pvBuffer; | ||
2399 | } | ||
2400 | |||
2401 | #define init_sec_buffer_empty(buffer, BufferType) init_sec_buffer(buffer, NULL, 0, BufferType) | ||
2402 | |||
2403 | static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, unsigned long buffer_count) { | ||
2404 | desc->ulVersion = SECBUFFER_VERSION; | ||
2405 | desc->cBuffers = buffer_count; | ||
2406 | desc->pBuffers = buffers; | ||
2407 | } | ||
2408 | |||
2409 | static ssize_t tls_read(tls_state_t *state, char *buf, ssize_t len) { | ||
2590 | ssize_t amount_read = 0; | 2410 | ssize_t amount_read = 0; |
2591 | 2411 | ||
2592 | if (state->closed) { | 2412 | if (state->connection_state > BB_SCHANNEL_OPEN) { |
2593 | return 0; | 2413 | goto Success; |
2594 | } | 2414 | } |
2595 | 2415 | ||
2596 | while (len > 0) { | 2416 | while (len > 0) { |
2597 | if (state->out_buffer && (state->out_buffer_size > 0)) { | 2417 | if (state->out_buffer) { |
2598 | unsigned long copy_amount = | 2418 | unsigned long copy_amount = |
2599 | min(len, (ssize_t) state->out_buffer_size); | 2419 | min(len, (ssize_t)state->out_buffer_length); |
2600 | memcpy(buf, state->out_buffer, copy_amount); | 2420 | memcpy(buf, state->out_buffer, copy_amount); |
2601 | 2421 | ||
2602 | amount_read += copy_amount; | 2422 | amount_read += copy_amount; |
2603 | buf += copy_amount; | 2423 | buf += copy_amount; |
2604 | len -= copy_amount; | 2424 | len -= copy_amount; |
2605 | 2425 | ||
2606 | if (copy_amount == state->out_buffer_size) { | 2426 | if (copy_amount == state->out_buffer_length) { |
2607 | // We've used all the decrypted data | 2427 | if (state->out_buffer_extra > 0) { |
2608 | // Move extra data to the front | 2428 | memmove( |
2609 | memmove(state->in_buffer, | 2429 | state->in_buffer, |
2610 | state->in_buffer + state->out_buffer_used, | 2430 | state->in_buffer + |
2611 | state->in_buffer_size - state->out_buffer_used); | 2431 | (state->in_buffer_offset - state->out_buffer_extra), |
2612 | state->in_buffer_size -= state->out_buffer_used; | 2432 | state->in_buffer_offset - (state->in_buffer_offset - |
2433 | state->out_buffer_extra)); | ||
2434 | state->in_buffer_offset = state->out_buffer_extra; | ||
2435 | } else { | ||
2436 | state->in_buffer_offset = 0; | ||
2437 | } | ||
2613 | 2438 | ||
2614 | state->out_buffer = NULL; | 2439 | state->out_buffer = NULL; |
2615 | state->out_buffer_used = 0; | 2440 | state->out_buffer_length = 0; |
2616 | state->out_buffer_size = 0; | 2441 | state->out_buffer_extra = 0; |
2442 | |||
2617 | } else { | 2443 | } else { |
2618 | state->out_buffer_size -= copy_amount; | 2444 | state->out_buffer_length -= copy_amount; |
2619 | state->out_buffer += copy_amount; | 2445 | state->out_buffer += copy_amount; |
2620 | } | 2446 | } |
2621 | } else { | 2447 | } else { |
2622 | SECURITY_STATUS status; | ||
2623 | |||
2624 | int received; | ||
2625 | |||
2626 | SecBuffer buffers[4]; | 2448 | SecBuffer buffers[4]; |
2627 | |||
2628 | SecBufferDesc desc; | 2449 | SecBufferDesc desc; |
2450 | SECURITY_STATUS status; | ||
2629 | 2451 | ||
2630 | buffers[0].BufferType = SECBUFFER_DATA; | 2452 | init_sec_buffer(&buffers[0], |
2631 | buffers[0].pvBuffer = state->in_buffer; | 2453 | state->in_buffer, |
2632 | buffers[0].cbBuffer = state->in_buffer_size; | 2454 | state->in_buffer_offset, |
2633 | 2455 | SECBUFFER_DATA); | |
2634 | buffers[1].BufferType = SECBUFFER_EMPTY; | 2456 | init_sec_buffer_empty(&buffers[1], SECBUFFER_EMPTY); |
2635 | buffers[1].pvBuffer = NULL; | 2457 | init_sec_buffer_empty(&buffers[2], SECBUFFER_EMPTY); |
2636 | buffers[1].cbBuffer = 0; | 2458 | init_sec_buffer_empty(&buffers[3], SECBUFFER_EMPTY); |
2637 | |||
2638 | buffers[2].BufferType = SECBUFFER_EMPTY; | ||
2639 | buffers[2].pvBuffer = NULL; | ||
2640 | buffers[2].cbBuffer = 0; | ||
2641 | |||
2642 | buffers[3].BufferType = SECBUFFER_EMPTY; | ||
2643 | buffers[3].pvBuffer = NULL; | ||
2644 | buffers[3].cbBuffer = 0; | ||
2645 | 2459 | ||
2646 | desc.ulVersion = SECBUFFER_VERSION; | 2460 | init_sec_buffer_desc(&desc, buffers, _countof(buffers)); |
2647 | desc.pBuffers = buffers; | ||
2648 | desc.cBuffers = _countof(buffers); | ||
2649 | 2461 | ||
2650 | status = DecryptMessage(&state->ctx_handle, &desc, 0, NULL); | 2462 | status = DecryptMessage(&state->ctx_handle, &desc, 0, NULL); |
2651 | 2463 | ||
2652 | switch (status) { | 2464 | switch (status) { |
2653 | case SEC_E_OK:{ | 2465 | case SEC_E_OK: { |
2654 | state->out_buffer = buffers[1].pvBuffer; | 2466 | state->out_buffer = buffers[1].pvBuffer; |
2655 | state->out_buffer_size = buffers[1].cbBuffer; | 2467 | state->out_buffer_length = buffers[1].cbBuffer; |
2656 | 2468 | state->out_buffer_extra = state->in_buffer_offset; | |
2657 | state->out_buffer_used = state->in_buffer_size; | 2469 | |
2658 | if (buffers[3].BufferType == SECBUFFER_EXTRA) { | 2470 | if (buffers[3].BufferType == SECBUFFER_EXTRA) { |
2659 | state->out_buffer_used -= buffers[3].cbBuffer; | 2471 | state->out_buffer_extra = buffers[3].cbBuffer; |
2472 | } else { | ||
2473 | state->out_buffer_extra = 0; | ||
2474 | } | ||
2475 | |||
2476 | continue; | ||
2660 | } | 2477 | } |
2661 | 2478 | case SEC_I_CONTEXT_EXPIRED: { | |
2662 | continue; | 2479 | // Shut down the connection |
2663 | } | 2480 | state->connection_state = BB_SCHANNEL_CLOSED; |
2664 | case SEC_I_CONTEXT_EXPIRED:{ | 2481 | goto Success; |
2665 | state->closed = 1; | ||
2666 | goto Success; | ||
2667 | } | ||
2668 | case SEC_I_RENEGOTIATE:{ | ||
2669 | // Renegotiate the TLS connection. | ||
2670 | // Microsoft repurposed this flag | ||
2671 | // for TLS 1.3 support. | ||
2672 | int i; | ||
2673 | |||
2674 | DWORD flags; | ||
2675 | |||
2676 | SecBuffer in_buffers[2]; | ||
2677 | |||
2678 | SecBuffer out_buffers[2]; | ||
2679 | |||
2680 | SecBufferDesc in_desc; | ||
2681 | |||
2682 | SecBufferDesc out_desc; | ||
2683 | |||
2684 | |||
2685 | for (i = 0; i < 4; i++) { | ||
2686 | if (buffers[i].BufferType == SECBUFFER_EXTRA) | ||
2687 | break; | ||
2688 | } | 2482 | } |
2689 | 2483 | case SEC_E_INCOMPLETE_MESSAGE: { | |
2690 | flags = BB_SCHANNEL_ISC_FLAGS; | 2484 | int result = safe_read(state->ifd, |
2691 | 2485 | state->in_buffer + state->in_buffer_offset, | |
2692 | in_buffers[0].BufferType = SECBUFFER_TOKEN; | 2486 | sizeof(state->in_buffer) - state->in_buffer_offset); |
2693 | in_buffers[0].pvBuffer = buffers[i].pvBuffer; | 2487 | if (result == 0) { |
2694 | in_buffers[0].cbBuffer = buffers[i].cbBuffer; | 2488 | state->connection_state = BB_SCHANNEL_CLOSED; |
2695 | 2489 | goto Success; | |
2696 | in_buffers[1].BufferType = SECBUFFER_EMPTY; | 2490 | } else if (result < 0) { |
2697 | in_buffers[1].pvBuffer = NULL; | 2491 | bb_error_msg_and_die("schannel: read() failed"); |
2698 | in_buffers[1].cbBuffer = 0; | 2492 | } |
2699 | 2493 | ||
2700 | out_buffers[0].BufferType = SECBUFFER_TOKEN; | 2494 | state->in_buffer_offset += result; |
2701 | out_buffers[0].pvBuffer = NULL; | 2495 | continue; |
2702 | out_buffers[0].cbBuffer = 0; | ||
2703 | |||
2704 | out_buffers[1].BufferType = SECBUFFER_ALERT; | ||
2705 | out_buffers[1].pvBuffer = NULL; | ||
2706 | out_buffers[1].cbBuffer = 0; | ||
2707 | |||
2708 | in_desc.ulVersion = SECBUFFER_VERSION; | ||
2709 | in_desc.pBuffers = in_buffers; | ||
2710 | in_desc.cBuffers = _countof(in_buffers); | ||
2711 | |||
2712 | out_desc.ulVersion = SECBUFFER_VERSION; | ||
2713 | out_desc.pBuffers = out_buffers; | ||
2714 | out_desc.cBuffers = _countof(out_buffers); | ||
2715 | |||
2716 | status = InitializeSecurityContext(&state->cred_handle, | ||
2717 | state->initialized ? | ||
2718 | &state->ctx_handle : NULL, | ||
2719 | state->initialized ? NULL : | ||
2720 | state->hostname, flags, 0, | ||
2721 | 0, | ||
2722 | state->initialized ? | ||
2723 | &in_desc : NULL, 0, | ||
2724 | state->initialized ? NULL : | ||
2725 | &state->ctx_handle, | ||
2726 | &out_desc, &flags, 0); | ||
2727 | |||
2728 | if (status != SEC_E_OK) { | ||
2729 | bb_error_msg_and_die("schannel: renegotiate failed: (0x%08lx): %s", | ||
2730 | status, hresult_to_error_string(status)); | ||
2731 | } | 2496 | } |
2732 | 2497 | case SEC_I_RENEGOTIATE: { | |
2733 | if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { | 2498 | DWORD flags = BB_SCHANNEL_ISC_FLAGS; |
2734 | memmove(state->in_buffer, | 2499 | |
2735 | state->in_buffer + (state->in_buffer_size - | 2500 | SecBuffer in_buffers[2]; |
2736 | in_buffers[1].cbBuffer), | 2501 | SecBufferDesc in_buffers_desc; |
2737 | in_buffers[1].cbBuffer); | 2502 | |
2503 | SecBuffer out_buffers[2]; | ||
2504 | SecBufferDesc out_buffers_desc; | ||
2505 | |||
2506 | init_sec_buffer(&in_buffers[0], | ||
2507 | buffers[3].pvBuffer, | ||
2508 | buffers[3].cbBuffer, | ||
2509 | SECBUFFER_TOKEN); | ||
2510 | init_sec_buffer_empty(&in_buffers[1], SECBUFFER_EMPTY); | ||
2511 | |||
2512 | init_sec_buffer_empty(&out_buffers[0], SECBUFFER_TOKEN); | ||
2513 | init_sec_buffer_empty(&out_buffers[1], SECBUFFER_ALERT); | ||
2514 | |||
2515 | init_sec_buffer_desc( | ||
2516 | &in_buffers_desc, in_buffers, _countof(in_buffers)); | ||
2517 | init_sec_buffer_desc( | ||
2518 | &out_buffers_desc, out_buffers, _countof(out_buffers)); | ||
2519 | |||
2520 | status = InitializeSecurityContextA(&state->cred_handle, | ||
2521 | &state->ctx_handle, | ||
2522 | state->hostname, | ||
2523 | flags, | ||
2524 | 0, | ||
2525 | 0, | ||
2526 | &in_buffers_desc, | ||
2527 | 0, | ||
2528 | &state->ctx_handle, | ||
2529 | &out_buffers_desc, | ||
2530 | &flags, | ||
2531 | 0); | ||
2532 | |||
2533 | if (SEC_STATUS_FAIL(status)) { | ||
2534 | bb_error_msg_and_die("schannel: renegotiate failed: (0x%08lx): %s", | ||
2535 | status, hresult_to_error_string(status)); | ||
2536 | } | ||
2537 | |||
2538 | if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { | ||
2539 | memmove(state->in_buffer, | ||
2540 | state->in_buffer + (state->in_buffer_offset - | ||
2541 | in_buffers[1].cbBuffer), | ||
2542 | in_buffers[1].cbBuffer); | ||
2543 | state->in_buffer_offset = in_buffers[1].cbBuffer; | ||
2544 | } else { | ||
2545 | state->in_buffer_offset = 0; | ||
2546 | } | ||
2547 | |||
2548 | continue; | ||
2549 | } | ||
2550 | default: { | ||
2551 | bb_error_msg_and_die("schannel: DecryptMessage failed: (0x%08lx): %s", | ||
2552 | status, hresult_to_error_string(status)); | ||
2738 | } | 2553 | } |
2739 | |||
2740 | state->out_buffer_used = | ||
2741 | state->in_buffer_size - in_buffers[1].cbBuffer; | ||
2742 | state->in_buffer_size = in_buffers[1].cbBuffer; | ||
2743 | |||
2744 | continue; | ||
2745 | } | ||
2746 | case SEC_E_INCOMPLETE_MESSAGE:{ | ||
2747 | break; | ||
2748 | } | ||
2749 | default:{ | ||
2750 | bb_error_msg_and_die("schannel: DecryptMessage failed: (0x%08lx): %s", status, | ||
2751 | hresult_to_error_string(status)); | ||
2752 | } | ||
2753 | } | ||
2754 | |||
2755 | received = | ||
2756 | safe_read(state->ifd, | ||
2757 | state->in_buffer + state->in_buffer_size, | ||
2758 | sizeof(state->in_buffer) - state->in_buffer_size); | ||
2759 | if (received == 0) { | ||
2760 | state->closed = 1; | ||
2761 | goto Success; | ||
2762 | } else if (received < 0) { | ||
2763 | bb_error_msg_and_die("schannel: read() failed"); | ||
2764 | } | 2554 | } |
2765 | |||
2766 | state->in_buffer_size += received; | ||
2767 | } | 2555 | } |
2768 | } | 2556 | } |
2769 | 2557 | ||
2770 | Success: | 2558 | Success: |
2771 | return amount_read; | 2559 | return amount_read; |
2772 | } | 2560 | } |
2773 | 2561 | ||
2774 | static void tls_write(struct tls_state *state, char *buf, size_t len) { | 2562 | static void tls_write(tls_state_t *state, char *buf, size_t len) { |
2775 | if (state->closed) { | 2563 | if (state->connection_state > BB_SCHANNEL_OPEN) { |
2776 | bb_error_msg_and_die("schannel: attempted to write to a closed connection"); | 2564 | bb_error_msg_and_die("schannel: attempted to write to a closed connection"); |
2777 | } | 2565 | } |
2778 | 2566 | ||
2779 | while (len > 0) { | 2567 | while (len > 0) { |
2568 | SECURITY_STATUS status; | ||
2780 | unsigned long copy_amount = | 2569 | unsigned long copy_amount = |
2781 | min(len, (size_t) state->stream_sizes.cbMaximumMessage); | 2570 | min(len, (size_t)state->stream_sizes.cbMaximumMessage); |
2782 | char *write_buffer = _alloca(sizeof(state->in_buffer)); | 2571 | char *write_buffer = _alloca(sizeof(state->in_buffer)); |
2783 | 2572 | ||
2784 | SECURITY_STATUS status; | ||
2785 | |||
2786 | SecBuffer buffers[4]; | 2573 | SecBuffer buffers[4]; |
2787 | |||
2788 | SecBufferDesc desc; | 2574 | SecBufferDesc desc; |
2789 | 2575 | ||
2790 | buffers[0].BufferType = SECBUFFER_STREAM_HEADER; | 2576 | init_sec_buffer(&buffers[0], |
2791 | buffers[0].pvBuffer = write_buffer; | 2577 | write_buffer, |
2792 | buffers[0].cbBuffer = state->stream_sizes.cbHeader; | 2578 | state->stream_sizes.cbHeader, |
2793 | 2579 | SECBUFFER_STREAM_HEADER); | |
2794 | buffers[1].BufferType = SECBUFFER_DATA; | 2580 | init_sec_buffer(&buffers[1], |
2795 | buffers[1].pvBuffer = write_buffer + state->stream_sizes.cbHeader; | 2581 | write_buffer + state->stream_sizes.cbHeader, |
2796 | buffers[1].cbBuffer = copy_amount; | 2582 | copy_amount, |
2797 | 2583 | SECBUFFER_DATA); | |
2798 | buffers[2].BufferType = SECBUFFER_STREAM_TRAILER; | 2584 | init_sec_buffer(&buffers[2], |
2799 | buffers[2].pvBuffer = | 2585 | write_buffer + state->stream_sizes.cbHeader + |
2800 | write_buffer + state->stream_sizes.cbHeader + copy_amount; | 2586 | copy_amount, |
2801 | buffers[2].cbBuffer = state->stream_sizes.cbTrailer; | 2587 | state->stream_sizes.cbTrailer, |
2802 | 2588 | SECBUFFER_STREAM_TRAILER); | |
2803 | buffers[3].BufferType = SECBUFFER_EMPTY; | 2589 | init_sec_buffer_empty(&buffers[3], SECBUFFER_EMPTY); |
2804 | buffers[3].pvBuffer = NULL; | 2590 | |
2805 | buffers[3].cbBuffer = 0; | 2591 | init_sec_buffer_desc(&desc, buffers, _countof(buffers)); |
2806 | 2592 | ||
2807 | memcpy(buffers[1].pvBuffer, buf, copy_amount); | 2593 | memcpy(buffers[1].pvBuffer, buf, copy_amount); |
2808 | 2594 | ||
2809 | desc.ulVersion = SECBUFFER_VERSION; | ||
2810 | desc.pBuffers = buffers; | ||
2811 | desc.cBuffers = _countof(buffers); | ||
2812 | |||
2813 | status = EncryptMessage(&state->ctx_handle, 0, &desc, 0); | 2595 | status = EncryptMessage(&state->ctx_handle, 0, &desc, 0); |
2814 | if (status != SEC_E_OK) { | 2596 | if (SEC_STATUS_FAIL(status)) { |
2815 | bb_error_msg_and_die("schannel: EncryptMessage failed: (0x%08lx): %s", status, | 2597 | bb_error_msg_and_die("schannel: EncryptMessage failed: (0x%08lx): %s", |
2816 | hresult_to_error_string(status)); | 2598 | status, hresult_to_error_string(status)); |
2817 | } | 2599 | } |
2818 | 2600 | ||
2819 | xwrite(state->ofd, write_buffer, | 2601 | xwrite(state->ofd, write_buffer, |
@@ -2826,72 +2608,44 @@ static void tls_write(struct tls_state *state, char *buf, size_t len) { | |||
2826 | 2608 | ||
2827 | static void tls_disconnect(tls_state_t * state) { | 2609 | static void tls_disconnect(tls_state_t * state) { |
2828 | SECURITY_STATUS status; | 2610 | SECURITY_STATUS status; |
2611 | |||
2829 | DWORD token = SCHANNEL_SHUTDOWN; | 2612 | DWORD token = SCHANNEL_SHUTDOWN; |
2830 | DWORD flags = BB_SCHANNEL_ISC_FLAGS; | 2613 | DWORD flags = BB_SCHANNEL_ISC_FLAGS; |
2831 | 2614 | ||
2832 | SecBuffer buf_token; | 2615 | SecBuffer buf_token; |
2833 | |||
2834 | SecBufferDesc buf_token_desc; | 2616 | SecBufferDesc buf_token_desc; |
2835 | |||
2836 | SecBuffer in_buffers[2]; | ||
2837 | SecBuffer out_buffers[2]; | ||
2838 | 2617 | ||
2839 | SecBufferDesc in_desc; | 2618 | SecBuffer out_buffer; |
2840 | SecBufferDesc out_desc; | 2619 | SecBufferDesc out_buffer_desc; |
2841 | 2620 | ||
2842 | buf_token.BufferType = SECBUFFER_TOKEN; | 2621 | if (state->connection_state == BB_SCHANNEL_CLOSED_AND_FREED) |
2843 | buf_token.pvBuffer = &token; | 2622 | return; |
2844 | buf_token.cbBuffer = sizeof(token); | 2623 | state->connection_state = BB_SCHANNEL_CLOSED_AND_FREED; |
2845 | 2624 | ||
2846 | buf_token_desc.ulVersion = SECBUFFER_VERSION; | 2625 | init_sec_buffer(&buf_token, &token, sizeof(token), SECBUFFER_TOKEN); |
2847 | buf_token_desc.pBuffers = &buf_token; | 2626 | init_sec_buffer_desc(&buf_token_desc, &buf_token, 1); |
2848 | buf_token_desc.cBuffers = 1; | ||
2849 | 2627 | ||
2850 | ApplyControlToken(&state->ctx_handle, &buf_token_desc); | 2628 | ApplyControlToken(&state->ctx_handle, &buf_token_desc); |
2851 | 2629 | ||
2852 | // attempt to send any final data | 2630 | init_sec_buffer_empty(&out_buffer, SECBUFFER_TOKEN); |
2853 | 2631 | init_sec_buffer_desc(&out_buffer_desc, &out_buffer, 1); | |
2854 | in_buffers[0].BufferType = SECBUFFER_TOKEN; | 2632 | |
2855 | in_buffers[0].pvBuffer = state->in_buffer; | 2633 | status = InitializeSecurityContextA(&state->cred_handle, |
2856 | in_buffers[0].cbBuffer = state->in_buffer_size; | 2634 | &state->ctx_handle, |
2857 | 2635 | state->hostname, | |
2858 | in_buffers[1].BufferType = SECBUFFER_EMPTY; | 2636 | flags, |
2859 | in_buffers[1].pvBuffer = NULL; | 2637 | 0, |
2860 | in_buffers[1].cbBuffer = 0; | 2638 | 0, |
2861 | 2639 | NULL, | |
2862 | out_buffers[0].BufferType = SECBUFFER_TOKEN; | 2640 | 0, |
2863 | out_buffers[0].pvBuffer = NULL; | 2641 | &state->ctx_handle, |
2864 | out_buffers[0].cbBuffer = 0; | 2642 | &out_buffer_desc, |
2865 | 2643 | &flags, | |
2866 | out_buffers[1].BufferType = SECBUFFER_ALERT; | 2644 | 0); |
2867 | out_buffers[1].pvBuffer = NULL; | 2645 | |
2868 | out_buffers[1].cbBuffer = 0; | 2646 | if ((status == SEC_E_OK) || (status == SEC_I_CONTEXT_EXPIRED)) { |
2869 | 2647 | write(state->ofd, out_buffer.pvBuffer, out_buffer.cbBuffer); | |
2870 | in_desc.ulVersion = SECBUFFER_VERSION; | 2648 | FreeContextBuffer(out_buffer.pvBuffer); |
2871 | in_desc.pBuffers = in_buffers; | ||
2872 | in_desc.cBuffers = _countof(in_buffers); | ||
2873 | |||
2874 | out_desc.ulVersion = SECBUFFER_VERSION; | ||
2875 | out_desc.pBuffers = out_buffers; | ||
2876 | out_desc.cBuffers = _countof(out_buffers); | ||
2877 | |||
2878 | status = InitializeSecurityContext(&state->cred_handle, | ||
2879 | state-> | ||
2880 | initialized ? &state->ctx_handle : | ||
2881 | NULL, | ||
2882 | state-> | ||
2883 | initialized ? NULL : state->hostname, | ||
2884 | flags, 0, 0, | ||
2885 | state->initialized ? &in_desc : NULL, | ||
2886 | 0, | ||
2887 | state-> | ||
2888 | initialized ? NULL : | ||
2889 | &state->ctx_handle, &out_desc, &flags, | ||
2890 | 0); | ||
2891 | |||
2892 | if (status == SEC_E_OK) { | ||
2893 | // attempt to write any extra data | ||
2894 | write(state->ofd, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer); | ||
2895 | } | 2649 | } |
2896 | 2650 | ||
2897 | DeleteSecurityContext(&state->ctx_handle); | 2651 | DeleteSecurityContext(&state->ctx_handle); |
@@ -2900,9 +2654,8 @@ static void tls_disconnect(tls_state_t * state) { | |||
2900 | } | 2654 | } |
2901 | 2655 | ||
2902 | 2656 | ||
2903 | void FAST_FUNC tls_handshake(tls_state_t * state, const char *hostname) { | 2657 | void FAST_FUNC tls_handshake(tls_state_t *state, const char *hostname) { |
2904 | SECURITY_STATUS status; | 2658 | SECURITY_STATUS status; |
2905 | int received; | ||
2906 | 2659 | ||
2907 | #if ENABLE_FEATURE_TLS_SCHANNEL_1_3 | 2660 | #if ENABLE_FEATURE_TLS_SCHANNEL_1_3 |
2908 | SCH_CREDENTIALS credential = {.dwVersion = SCH_CREDENTIALS_VERSION, | 2661 | SCH_CREDENTIALS credential = {.dwVersion = SCH_CREDENTIALS_VERSION, |
@@ -2941,133 +2694,124 @@ void FAST_FUNC tls_handshake(tls_state_t * state, const char *hostname) { | |||
2941 | }; | 2694 | }; |
2942 | #endif | 2695 | #endif |
2943 | 2696 | ||
2944 | if ((status = AcquireCredentialsHandleA(NULL, (SEC_CHAR *) UNISP_NAME_A, | 2697 | state->in_buffer_offset = 0; |
2945 | SECPKG_CRED_OUTBOUND, NULL, | ||
2946 | &credential, | ||
2947 | NULL, NULL, &state->cred_handle, | ||
2948 | NULL)) != SEC_E_OK) { | ||
2949 | bb_error_msg_and_die("schannel: AcquireCredentialsHandleA failed: (0x%08lx): %s", | ||
2950 | status, hresult_to_error_string(status)); | ||
2951 | } | ||
2952 | |||
2953 | state->in_buffer_size = 0; | ||
2954 | state->out_buffer_size = 0; | ||
2955 | state->out_buffer_used = 0; | ||
2956 | 2698 | ||
2957 | state->out_buffer = NULL; | 2699 | state->out_buffer = NULL; |
2700 | state->out_buffer_length = 0; | ||
2701 | state->out_buffer_extra = 0; | ||
2702 | |||
2703 | state->hostname = xstrdup(hostname); | ||
2704 | state->initialized = false; | ||
2705 | state->connection_state = BB_SCHANNEL_OPEN; | ||
2706 | |||
2707 | if (SEC_STATUS_FAIL(status = AcquireCredentialsHandleA(NULL, | ||
2708 | (SEC_CHAR *)UNISP_NAME_A, | ||
2709 | SECPKG_CRED_OUTBOUND, | ||
2710 | NULL, | ||
2711 | &credential, | ||
2712 | NULL, | ||
2713 | NULL, | ||
2714 | &state->cred_handle, | ||
2715 | NULL))) { | ||
2716 | bb_error_msg_and_die("schannel: AcquireCredentialsHandleA failed: (0x%08lx): %s", | ||
2717 | status, hresult_to_error_string(status)); | ||
2718 | } | ||
2958 | 2719 | ||
2959 | state->hostname = strdup(hostname); | 2720 | // InitializeSecurityContext loop |
2960 | 2721 | while (true) { | |
2961 | state->initialized = 0; | ||
2962 | state->closed = 0; | ||
2963 | |||
2964 | while (1) { | ||
2965 | DWORD flags = BB_SCHANNEL_ISC_FLAGS; | 2722 | DWORD flags = BB_SCHANNEL_ISC_FLAGS; |
2966 | 2723 | ||
2967 | SecBuffer in_buffers[2]; | 2724 | SecBuffer in_buffers[2]; |
2968 | SecBuffer out_buffers[2]; | 2725 | SecBufferDesc in_buffers_desc; |
2969 | |||
2970 | SecBufferDesc in_desc; | ||
2971 | SecBufferDesc out_desc; | ||
2972 | |||
2973 | in_buffers[0].BufferType = SECBUFFER_TOKEN; | ||
2974 | in_buffers[0].pvBuffer = state->in_buffer; | ||
2975 | in_buffers[0].cbBuffer = state->in_buffer_size; | ||
2976 | |||
2977 | in_buffers[1].BufferType = SECBUFFER_EMPTY; | ||
2978 | in_buffers[1].pvBuffer = NULL; | ||
2979 | in_buffers[1].cbBuffer = 0; | ||
2980 | 2726 | ||
2981 | out_buffers[0].BufferType = SECBUFFER_TOKEN; | 2727 | SecBuffer out_buffers[2]; |
2982 | out_buffers[0].pvBuffer = NULL; | 2728 | SecBufferDesc out_buffers_desc; |
2983 | out_buffers[0].cbBuffer = 0; | 2729 | |
2984 | 2730 | init_sec_buffer(&in_buffers[0], | |
2985 | out_buffers[1].BufferType = SECBUFFER_ALERT; | 2731 | state->in_buffer, |
2986 | out_buffers[1].pvBuffer = NULL; | 2732 | state->in_buffer_offset, |
2987 | out_buffers[1].cbBuffer = 0; | 2733 | SECBUFFER_TOKEN); |
2988 | 2734 | init_sec_buffer_empty(&in_buffers[1], SECBUFFER_EMPTY); | |
2989 | in_desc.ulVersion = SECBUFFER_VERSION; | 2735 | |
2990 | in_desc.pBuffers = in_buffers; | 2736 | init_sec_buffer_empty(&out_buffers[0], SECBUFFER_TOKEN); |
2991 | in_desc.cBuffers = _countof(in_buffers); | 2737 | init_sec_buffer_empty(&out_buffers[1], SECBUFFER_ALERT); |
2992 | 2738 | ||
2993 | out_desc.ulVersion = SECBUFFER_VERSION; | 2739 | init_sec_buffer_desc( |
2994 | out_desc.pBuffers = out_buffers; | 2740 | &in_buffers_desc, in_buffers, _countof(in_buffers)); |
2995 | out_desc.cBuffers = _countof(out_buffers); | 2741 | init_sec_buffer_desc( |
2996 | 2742 | &out_buffers_desc, out_buffers, _countof(out_buffers)); | |
2997 | status = InitializeSecurityContext(&state->cred_handle, | 2743 | |
2998 | state-> | 2744 | status = InitializeSecurityContextA( |
2999 | initialized ? &state->ctx_handle : | 2745 | &state->cred_handle, |
3000 | NULL, | 2746 | state->initialized ? &state->ctx_handle : NULL, |
3001 | state-> | 2747 | state->hostname, |
3002 | initialized ? NULL : | 2748 | flags, |
3003 | state->hostname, flags, 0, 0, | 2749 | 0, |
3004 | state->initialized ? &in_desc : | 2750 | 0, |
3005 | NULL, 0, | 2751 | state->initialized ? &in_buffers_desc : NULL, |
3006 | state->initialized ? NULL : | 2752 | 0, |
3007 | &state->ctx_handle, &out_desc, | 2753 | &state->ctx_handle, |
3008 | &flags, 0); | 2754 | &out_buffers_desc, |
3009 | 2755 | &flags, | |
3010 | state->initialized = 1; | 2756 | 0); |
2757 | |||
2758 | state->initialized = true; | ||
3011 | 2759 | ||
3012 | if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { | 2760 | if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { |
3013 | memmove(state->in_buffer, | 2761 | memmove(state->in_buffer, |
3014 | state->in_buffer + (state->in_buffer_size - | 2762 | state->in_buffer + |
3015 | in_buffers[1].cbBuffer), | 2763 | (state->in_buffer_offset - in_buffers[1].cbBuffer), |
3016 | in_buffers[1].cbBuffer); | 2764 | in_buffers[1].cbBuffer); |
3017 | state->in_buffer_size = in_buffers[1].cbBuffer; | 2765 | state->in_buffer_offset = in_buffers[1].cbBuffer; |
3018 | } else if (in_buffers[1].BufferType != SECBUFFER_MISSING) { | ||
3019 | state->in_buffer_size = 0; | ||
3020 | } | 2766 | } |
3021 | 2767 | ||
3022 | switch (status) { | 2768 | switch (status) { |
3023 | case SEC_E_OK:{ | 2769 | case SEC_E_OK: { |
3024 | if (out_buffers[0].cbBuffer > 0) { | 2770 | state->in_buffer_offset = |
3025 | xwrite(state->ofd, out_buffers[0].pvBuffer, | 2771 | (in_buffers[1].BufferType == SECBUFFER_EXTRA) |
3026 | out_buffers[0].cbBuffer); | 2772 | ? in_buffers[1].cbBuffer |
2773 | : 0; | ||
2774 | |||
2775 | if (out_buffers[0].cbBuffer > 0) { | ||
2776 | xwrite(state->ifd, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer); | ||
2777 | FreeContextBuffer(out_buffers[0].pvBuffer); | ||
2778 | } | ||
2779 | |||
2780 | goto Success; | ||
2781 | } | ||
2782 | case SEC_I_CONTINUE_NEEDED: { | ||
2783 | xwrite(state->ofd, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer); | ||
3027 | FreeContextBuffer(out_buffers[0].pvBuffer); | 2784 | FreeContextBuffer(out_buffers[0].pvBuffer); |
2785 | if (in_buffers[1].BufferType != SECBUFFER_EXTRA) { | ||
2786 | state->in_buffer_offset = 0; | ||
2787 | } | ||
2788 | break; | ||
3028 | } | 2789 | } |
3029 | goto Success; | 2790 | case SEC_E_INCOMPLETE_MESSAGE: { |
3030 | } | 2791 | int amount_read = |
3031 | case SEC_I_CONTINUE_NEEDED:{ | 2792 | safe_read(state->ifd, state->in_buffer + state->in_buffer_offset, |
3032 | xwrite(state->ofd, out_buffers[0].pvBuffer, | 2793 | sizeof(state->in_buffer) - state->in_buffer_offset); |
3033 | out_buffers[0].cbBuffer); | 2794 | if (amount_read <= 0) { |
3034 | FreeContextBuffer(out_buffers[0].pvBuffer); | 2795 | bb_error_msg_and_die("schannel: handshake read() failed"); |
3035 | break; | 2796 | } |
3036 | } | ||
3037 | case SEC_I_INCOMPLETE_CREDENTIALS:{ | ||
3038 | // we don't support this | ||
3039 | bb_error_msg_and_die("schannel: client certificates not supported"); | ||
3040 | } | ||
3041 | case SEC_E_INCOMPLETE_MESSAGE:{ | ||
3042 | break; | ||
3043 | } | ||
3044 | default:{ | ||
3045 | bb_error_msg_and_die("schannel: handshake failed: (0x%08lx): %s", | ||
3046 | status, hresult_to_error_string(status)); | ||
3047 | } | ||
3048 | } | ||
3049 | 2797 | ||
3050 | received = | 2798 | state->in_buffer_offset += amount_read; |
3051 | safe_read(state->ifd, state->in_buffer + state->in_buffer_size, | 2799 | continue; |
3052 | sizeof(state->in_buffer) - state->in_buffer_size); | 2800 | } |
3053 | if (received <= 0) { | 2801 | default: { |
3054 | bb_error_msg_and_die("schannel: handshake read() failed"); | 2802 | bb_error_msg_and_die("schannel: handshake failed: (0x%08lx): %s", |
2803 | status, hresult_to_error_string(status)); | ||
2804 | } | ||
3055 | } | 2805 | } |
3056 | state->in_buffer_size += received; | ||
3057 | } | 2806 | } |
3058 | 2807 | ||
3059 | Success: | 2808 | Success: |
3060 | QueryContextAttributes(&state->ctx_handle, SECPKG_ATTR_STREAM_SIZES, | 2809 | QueryContextAttributes( |
3061 | &state->stream_sizes); | 2810 | &state->ctx_handle, SECPKG_ATTR_STREAM_SIZES, &state->stream_sizes); |
3062 | 2811 | return; | |
3063 | //SecPkgContext_ConnectionInfo info; | ||
3064 | //QueryContextAttributes(&state->ctx_handle, SECPKG_ATTR_CONNECTION_INFO, | ||
3065 | // &info); | ||
3066 | // | ||
3067 | //fprintf(stderr, "TLS 1.%d\n", (((uint32_t)(8 * sizeof(unsigned long long) - __builtin_clzll((info.dwProtocol)) - 1)) - 7)/2); | ||
3068 | } | 2812 | } |
3069 | 2813 | ||
3070 | void FAST_FUNC tls_run_copy_loop(tls_state_t * tls, unsigned flags) { | 2814 | void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) { |
3071 | char buffer[65536]; | 2815 | char buffer[65536]; |
3072 | 2816 | ||
3073 | struct pollfd pfds[2]; | 2817 | struct pollfd pfds[2]; |
@@ -3104,4 +2848,4 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t * tls, unsigned flags) { | |||
3104 | } | 2848 | } |
3105 | } | 2849 | } |
3106 | } | 2850 | } |
3107 | #endif \ No newline at end of file | 2851 | #endif |
diff --git a/networking/tls.h b/networking/tls.h index b34c678c8..eee5a7617 100644 --- a/networking/tls.h +++ b/networking/tls.h | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | #include "libbb.h" | 11 | #include "libbb.h" |
12 | 12 | ||
13 | |||
13 | #if !ENABLE_FEATURE_TLS_SCHANNEL | 14 | #if !ENABLE_FEATURE_TLS_SCHANNEL |
14 | /* Config tweaks */ | 15 | /* Config tweaks */ |
15 | #define HAVE_NATIVE_INT64 | 16 | #define HAVE_NATIVE_INT64 |
@@ -82,10 +83,9 @@ typedef int16_t int16; | |||
82 | 83 | ||
83 | void tls_get_random(void *buf, unsigned len) FAST_FUNC; | 84 | void tls_get_random(void *buf, unsigned len) FAST_FUNC; |
84 | 85 | ||
85 | void xorbuf(void* buf, const void* mask, unsigned count) FAST_FUNC; | ||
86 | |||
87 | #define ALIGNED_long ALIGNED(sizeof(long)) | 86 | #define ALIGNED_long ALIGNED(sizeof(long)) |
88 | void xorbuf_aligned_AES_BLOCK_SIZE(void* buf, const void* mask) FAST_FUNC; | 87 | #define xorbuf_aligned_AES_BLOCK_SIZE(dst,src) xorbuf16_aligned_long(dst,src) |
88 | #define xorbuf_AES_BLOCK_SIZE(dst,src) xorbuf16(dst,src) | ||
89 | 89 | ||
90 | #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) | 90 | #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) |
91 | 91 | ||
diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index 5ddcdd2ad..9c2381a57 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c | |||
@@ -167,10 +167,7 @@ void FAST_FUNC aesgcm_GHASH(byte* h, | |||
167 | blocks = cSz / AES_BLOCK_SIZE; | 167 | blocks = cSz / AES_BLOCK_SIZE; |
168 | partial = cSz % AES_BLOCK_SIZE; | 168 | partial = cSz % AES_BLOCK_SIZE; |
169 | while (blocks--) { | 169 | while (blocks--) { |
170 | if (BB_UNALIGNED_MEMACCESS_OK) // c is not guaranteed to be aligned | 170 | xorbuf_AES_BLOCK_SIZE(x, c); |
171 | xorbuf_aligned_AES_BLOCK_SIZE(x, c); | ||
172 | else | ||
173 | xorbuf(x, c, AES_BLOCK_SIZE); | ||
174 | GMULT(x, h); | 171 | GMULT(x, h); |
175 | c += AES_BLOCK_SIZE; | 172 | c += AES_BLOCK_SIZE; |
176 | } | 173 | } |