aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
Diffstat (limited to 'networking')
-rw-r--r--networking/Config.src30
-rw-r--r--networking/hostname.c4
-rw-r--r--networking/httpd.c2
-rw-r--r--networking/libiproute/iproute.c16
-rw-r--r--networking/ntpd.c6
-rw-r--r--networking/telnetd.c4
-rw-r--r--networking/tftp.c2
-rw-r--r--networking/tls.c769
-rw-r--r--networking/tls.h7
-rw-r--r--networking/tls_aesgcm.c5
-rw-r--r--networking/udhcp/d6_dhcpc.c193
-rw-r--r--networking/udhcp/d6_packet.c16
-rw-r--r--networking/udhcp/dhcpd.c58
13 files changed, 827 insertions, 285 deletions
diff --git a/networking/Config.src b/networking/Config.src
index 0942645c3..aa0806a18 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -72,9 +72,28 @@ config FEATURE_HWIB
72 help 72 help
73 Support for printing infiniband addresses in network applets. 73 Support for printing infiniband addresses in network applets.
74 74
75choice
76 prompt "TLS implementation"
77 default FEATURE_TLS_INTERNAL
78
79config FEATURE_TLS_INTERNAL
80 bool "Internal"
81 depends on TLS
82 help
83 Use the BusyBox default internal TLS implementation.
84
85config FEATURE_TLS_SCHANNEL
86 bool "Schannel SSP"
87 depends on TLS && PLATFORM_MINGW32
88 help
89 Use the Schannel SSP to provide TLS support.
90 Reduces code size and enables certificate checking.
91
92endchoice
93
75config FEATURE_TLS_SHA1 94config FEATURE_TLS_SHA1
76 bool "In TLS code, support ciphers which use deprecated SHA1" 95 bool "In TLS code, support ciphers which use deprecated SHA1"
77 depends on TLS 96 depends on FEATURE_TLS_INTERNAL
78 default n 97 default n
79 help 98 help
80 Selecting this option increases interoperability with very old 99 Selecting this option increases interoperability with very old
@@ -83,6 +102,15 @@ config FEATURE_TLS_SHA1
83 Most TLS servers support SHA256 today (2018), since SHA1 is 102 Most TLS servers support SHA256 today (2018), since SHA1 is
84 considered possibly insecure (although not yet definitely broken). 103 considered possibly insecure (although not yet definitely broken).
85 104
105config FEATURE_TLS_SCHANNEL_1_3
106 bool "Enable TLS 1.3 support for Schannel"
107 depends on FEATURE_TLS_SCHANNEL
108 default n
109 help
110 Enable TLS 1.3 support for Schannel.
111 This only works on Windows 11/Server 2022
112 and up.
113
86INSERT 114INSERT
87 115
88source networking/udhcp/Config.in 116source networking/udhcp/Config.in
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 9f1dd67ec..9c05364ea 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -10,18 +10,19 @@
10//Config.src also defines FEATURE_TLS_SHA1 option 10//Config.src also defines FEATURE_TLS_SHA1 option
11 11
12//kbuild:lib-$(CONFIG_TLS) += tls.o 12//kbuild:lib-$(CONFIG_TLS) += tls.o
13//kbuild:lib-$(CONFIG_TLS) += tls_pstm.o 13//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm.o
14//kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o 14//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm_montgomery_reduce.o
15//kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o 15//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm_mul_comba.o
16//kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o 16//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm_sqr_comba.o
17//kbuild:lib-$(CONFIG_TLS) += tls_aes.o 17//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_aes.o
18//kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o 18//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_aesgcm.o
19//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o 19//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_rsa.o
20//kbuild:lib-$(CONFIG_TLS) += tls_fe.o 20//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_fe.o
21//kbuild:lib-$(CONFIG_TLS) += tls_sp_c32.o 21//kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_sp_c32.o
22 22
23#include "tls.h" 23#include "tls.h"
24 24
25#if !ENABLE_FEATURE_TLS_SCHANNEL
25// Usually enabled. You can disable some of them to force only 26// Usually enabled. You can disable some of them to force only
26// specific ciphers to be advertized to server. 27// specific ciphers to be advertized to server.
27// (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)
@@ -188,8 +189,6 @@
188#define TLS_MAX_OUTBUF (1 << 14) 189#define TLS_MAX_OUTBUF (1 << 14)
189 190
190enum { 191enum {
191 SHA_INSIZE = 64,
192
193 AES128_KEYSIZE = 16, 192 AES128_KEYSIZE = 16,
194 AES256_KEYSIZE = 32, 193 AES256_KEYSIZE = 32,
195 194
@@ -335,34 +334,6 @@ void FAST_FUNC tls_get_random(void *buf, unsigned len)
335 xfunc_die(); 334 xfunc_die();
336} 335}
337 336
338static void xorbuf3(void *dst, const void *src1, const void *src2, unsigned count)
339{
340 uint8_t *d = dst;
341 const uint8_t *s1 = src1;
342 const uint8_t* s2 = src2;
343 while (count--)
344 *d++ = *s1++ ^ *s2++;
345}
346
347void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count)
348{
349 xorbuf3(dst, dst, src, count);
350}
351
352void FAST_FUNC xorbuf_aligned_AES_BLOCK_SIZE(void *dst, const void *src)
353{
354 unsigned long *d = dst;
355 const unsigned long *s = src;
356 d[0] ^= s[0];
357#if ULONG_MAX <= 0xffffffffffffffff
358 d[1] ^= s[1];
359 #if ULONG_MAX == 0xffffffff
360 d[2] ^= s[2];
361 d[3] ^= s[3];
362 #endif
363#endif
364}
365
366#if !TLS_DEBUG_HASH 337#if !TLS_DEBUG_HASH
367# define hash_handshake(tls, fmt, buffer, len) \ 338# define hash_handshake(tls, fmt, buffer, len) \
368 hash_handshake(tls, buffer, len) 339 hash_handshake(tls, buffer, len)
@@ -393,128 +364,6 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer
393# define TLS_MAC_SIZE(tls) (tls)->MAC_size 364# define TLS_MAC_SIZE(tls) (tls)->MAC_size
394#endif 365#endif
395 366
396// RFC 2104:
397// HMAC(key, text) based on a hash H (say, sha256) is:
398// ipad = [0x36 x INSIZE]
399// opad = [0x5c x INSIZE]
400// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text))
401//
402// H(key XOR opad) and H(key XOR ipad) can be precomputed
403// if we often need HMAC hmac with the same key.
404//
405// text is often given in disjoint pieces.
406typedef struct hmac_precomputed {
407 md5sha_ctx_t hashed_key_xor_ipad;
408 md5sha_ctx_t hashed_key_xor_opad;
409} hmac_precomputed_t;
410
411typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC;
412#if !ENABLE_FEATURE_TLS_SHA1
413#define hmac_begin(pre,key,key_size,begin) \
414 hmac_begin(pre,key,key_size)
415#define begin sha256_begin
416#endif
417static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
418{
419 uint8_t key_xor_ipad[SHA_INSIZE];
420 uint8_t key_xor_opad[SHA_INSIZE];
421// uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE];
422 unsigned i;
423
424 // "The authentication key can be of any length up to INSIZE, the
425 // block length of the hash function. Applications that use keys longer
426 // than INSIZE bytes will first hash the key using H and then use the
427 // resultant OUTSIZE byte string as the actual key to HMAC."
428 if (key_size > SHA_INSIZE) {
429 bb_simple_error_msg_and_die("HMAC key>64"); //does not happen (yet?)
430// md5sha_ctx_t ctx;
431// begin(&ctx);
432// md5sha_hash(&ctx, key, key_size);
433// key_size = sha_end(&ctx, tempkey);
434// //key = tempkey; - right? RIGHT? why does it work without this?
435// // because SHA_INSIZE is 64, but hmac() is always called with
436// // key_size = tls->MAC_size = SHA1/256_OUTSIZE (20 or 32),
437// // and prf_hmac_sha256() -> hmac_sha256() key sizes are:
438// // - RSA_PREMASTER_SIZE is 48
439// // - CURVE25519_KEYSIZE is 32
440// // - master_secret[] is 48
441 }
442
443 for (i = 0; i < key_size; i++) {
444 key_xor_ipad[i] = key[i] ^ 0x36;
445 key_xor_opad[i] = key[i] ^ 0x5c;
446 }
447 for (; i < SHA_INSIZE; i++) {
448 key_xor_ipad[i] = 0x36;
449 key_xor_opad[i] = 0x5c;
450 }
451
452 begin(&pre->hashed_key_xor_ipad);
453 begin(&pre->hashed_key_xor_opad);
454 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE);
455 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
456}
457#undef begin
458
459static unsigned hmac_sha_precomputed_v(
460 hmac_precomputed_t *pre,
461 uint8_t *out,
462 va_list va)
463{
464 uint8_t *text;
465 unsigned len;
466
467 /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
468 /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
469
470 /* calculate out = H((key XOR ipad) + text) */
471 while ((text = va_arg(va, uint8_t*)) != NULL) {
472 unsigned text_size = va_arg(va, unsigned);
473 md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size);
474 }
475 len = sha_end(&pre->hashed_key_xor_ipad, out);
476
477 /* out = H((key XOR opad) + out) */
478 md5sha_hash(&pre->hashed_key_xor_opad, out, len);
479 return sha_end(&pre->hashed_key_xor_opad, out);
480}
481
482static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out, ...)
483{
484 hmac_precomputed_t pre;
485 va_list va;
486 unsigned len;
487
488 va_start(va, out);
489 pre = *pre_init; /* struct copy */
490 len = hmac_sha_precomputed_v(&pre, out, va);
491 va_end(va);
492 return len;
493}
494
495#if !ENABLE_FEATURE_TLS_SHA1
496#define hmac(tls,out,key,key_size,...) \
497 hmac(out,key,key_size, __VA_ARGS__)
498#endif
499static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
500{
501 hmac_precomputed_t pre;
502 va_list va;
503 unsigned len;
504
505 va_start(va, key_size);
506
507 hmac_begin(&pre, key, key_size,
508 (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE)
509 ? sha1_begin
510 : sha256_begin
511 );
512 len = hmac_sha_precomputed_v(&pre, out, va);
513
514 va_end(va);
515 return len;
516}
517
518// RFC 5246: 367// RFC 5246:
519// 5. HMAC and the Pseudorandom Function 368// 5. HMAC and the Pseudorandom Function
520//... 369//...
@@ -559,7 +408,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
559 const char *label, 408 const char *label,
560 uint8_t *seed, unsigned seed_size) 409 uint8_t *seed, unsigned seed_size)
561{ 410{
562 hmac_precomputed_t pre; 411 hmac_ctx_t ctx;
563 uint8_t a[TLS_MAX_MAC_SIZE]; 412 uint8_t a[TLS_MAX_MAC_SIZE];
564 uint8_t *out_p = outbuf; 413 uint8_t *out_p = outbuf;
565 unsigned label_size = strlen(label); 414 unsigned label_size = strlen(label);
@@ -569,26 +418,27 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
569#define SEED label, label_size, seed, seed_size 418#define SEED label, label_size, seed, seed_size
570#define A a, MAC_size 419#define A a, MAC_size
571 420
572 hmac_begin(&pre, secret, secret_size, sha256_begin); 421 hmac_begin(&ctx, secret, secret_size, sha256_begin_hmac);
573 422
574 /* A(1) = HMAC_hash(secret, seed) */ 423 /* A(1) = HMAC_hash(secret, seed) */
575 hmac_sha_precomputed(&pre, a, SEED, NULL); 424 hmac_peek_hash(&ctx, a, SEED, NULL);
576 425
577 for (;;) { 426 for (;;) {
578 /* HMAC_hash(secret, A(1) + seed) */ 427 /* HMAC_hash(secret, A(1) + seed) */
579 if (outbuf_size <= MAC_size) { 428 if (outbuf_size <= MAC_size) {
580 /* Last, possibly incomplete, block */ 429 /* Last, possibly incomplete, block */
581 /* (use a[] as temp buffer) */ 430 /* (use a[] as temp buffer) */
582 hmac_sha_precomputed(&pre, a, A, SEED, NULL); 431 hmac_peek_hash(&ctx, a, A, SEED, NULL);
583 memcpy(out_p, a, outbuf_size); 432 memcpy(out_p, a, outbuf_size);
433 hmac_uninit(&ctx);
584 return; 434 return;
585 } 435 }
586 /* Not last block. Store directly to result buffer */ 436 /* Not last block. Store directly to result buffer */
587 hmac_sha_precomputed(&pre, out_p, A, SEED, NULL); 437 hmac_peek_hash(&ctx, out_p, A, SEED, NULL);
588 out_p += MAC_size; 438 out_p += MAC_size;
589 outbuf_size -= MAC_size; 439 outbuf_size -= MAC_size;
590 /* A(2) = HMAC_hash(secret, A(1)) */ 440 /* A(2) = HMAC_hash(secret, A(1)) */
591 hmac_sha_precomputed(&pre, a, A, NULL); 441 hmac_peek_hash(&ctx, a, A, NULL);
592 } 442 }
593#undef A 443#undef A
594#undef SECRET 444#undef SECRET
@@ -655,6 +505,32 @@ static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len)
655 return record; 505 return record;
656} 506}
657 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
513static 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
658static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) 534static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type)
659{ 535{
660 uint8_t *buf = tls->outbuf + OUTBUF_PFX; 536 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
@@ -676,7 +552,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un
676 xhdr->len16_lo = size & 0xff; 552 xhdr->len16_lo = size & 0xff;
677 553
678 /* Calculate MAC signature */ 554 /* Calculate MAC signature */
679 hmac(tls, buf + size, /* result */ 555 hmac_blocks(tls, buf + size, /* result */
680 tls->client_write_MAC_key, TLS_MAC_SIZE(tls), 556 tls->client_write_MAC_key, TLS_MAC_SIZE(tls),
681 &tls->write_seq64_be, sizeof(tls->write_seq64_be), 557 &tls->write_seq64_be, sizeof(tls->write_seq64_be),
682 xhdr, RECHDR_LEN, 558 xhdr, RECHDR_LEN,
@@ -865,8 +741,13 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty
865 cnt++; 741 cnt++;
866 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ 742 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */
867 aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); 743 aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch);
868 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; 744 if (remaining >= AES_BLOCK_SIZE) {
869 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 }
870 buf += n; 751 buf += n;
871 remaining -= n; 752 remaining -= n;
872 } 753 }
@@ -1024,7 +905,7 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size)
1024 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ 905 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */
1025 aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); 906 aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch);
1026 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; 907 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining;
1027 xorbuf3(buf, scratch, buf + 8, n); 908 xorbuf_3(buf, scratch, buf + 8, n);
1028 buf += n; 909 buf += n;
1029 remaining -= n; 910 remaining -= n;
1030 } 911 }
@@ -2481,3 +2362,549 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags)
2481 } 2362 }
2482 } 2363 }
2483} 2364}
2365#else
2366
2367#if ENABLE_FEATURE_TLS_SCHANNEL_1_3
2368#include <subauth.h>
2369#endif
2370
2371#define SCHANNEL_USE_BLACKLISTS
2372
2373#include <security.h>
2374#include <schannel.h>
2375
2376
2377#define BB_SCHANNEL_ISC_FLAGS \
2378 (ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_REPLAY_DETECT | \
2379 ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS)
2380
2381static char *hresult_to_error_string(HRESULT result) {
2382 char *output = NULL;
2383
2384 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
2385 | FORMAT_MESSAGE_IGNORE_INSERTS |
2386 FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, result,
2387 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2388 (char *) &output, 0, NULL);
2389 return output;
2390}
2391
2392static ssize_t tls_read(struct tls_state *state, char *buf, ssize_t len) {
2393 ssize_t amount_read = 0;
2394
2395 if (state->closed) {
2396 return 0;
2397 }
2398
2399 while (len > 0) {
2400 if (state->out_buffer && (state->out_buffer_size > 0)) {
2401 unsigned long copy_amount =
2402 min(len, (ssize_t) state->out_buffer_size);
2403 memcpy(buf, state->out_buffer, copy_amount);
2404
2405 amount_read += copy_amount;
2406 buf += copy_amount;
2407 len -= copy_amount;
2408
2409 if (copy_amount == state->out_buffer_size) {
2410 // We've used all the decrypted data
2411 // Move extra data to the front
2412 memmove(state->in_buffer,
2413 state->in_buffer + state->out_buffer_used,
2414 state->in_buffer_size - state->out_buffer_used);
2415 state->in_buffer_size -= state->out_buffer_used;
2416
2417 state->out_buffer = NULL;
2418 state->out_buffer_used = 0;
2419 state->out_buffer_size = 0;
2420 } else {
2421 state->out_buffer_size -= copy_amount;
2422 state->out_buffer += copy_amount;
2423 }
2424 } else {
2425 SECURITY_STATUS status;
2426
2427 int received;
2428
2429 SecBuffer buffers[4];
2430
2431 SecBufferDesc desc;
2432
2433 buffers[0].BufferType = SECBUFFER_DATA;
2434 buffers[0].pvBuffer = state->in_buffer;
2435 buffers[0].cbBuffer = state->in_buffer_size;
2436
2437 buffers[1].BufferType = SECBUFFER_EMPTY;
2438 buffers[1].pvBuffer = NULL;
2439 buffers[1].cbBuffer = 0;
2440
2441 buffers[2].BufferType = SECBUFFER_EMPTY;
2442 buffers[2].pvBuffer = NULL;
2443 buffers[2].cbBuffer = 0;
2444
2445 buffers[3].BufferType = SECBUFFER_EMPTY;
2446 buffers[3].pvBuffer = NULL;
2447 buffers[3].cbBuffer = 0;
2448
2449 desc.ulVersion = SECBUFFER_VERSION;
2450 desc.pBuffers = buffers;
2451 desc.cBuffers = _countof(buffers);
2452
2453 status = DecryptMessage(&state->ctx_handle, &desc, 0, NULL);
2454
2455 switch (status) {
2456 case SEC_E_OK:{
2457 state->out_buffer = buffers[1].pvBuffer;
2458 state->out_buffer_size = buffers[1].cbBuffer;
2459
2460 state->out_buffer_used = state->in_buffer_size;
2461 if (buffers[3].BufferType == SECBUFFER_EXTRA) {
2462 state->out_buffer_used -= buffers[3].cbBuffer;
2463 }
2464
2465 continue;
2466 }
2467 case SEC_I_CONTEXT_EXPIRED:{
2468 state->closed = 1;
2469 goto Success;
2470 }
2471 case SEC_I_RENEGOTIATE:{
2472 // Renegotiate the TLS connection.
2473 // Microsoft repurposed this flag
2474 // for TLS 1.3 support.
2475 int i;
2476
2477 DWORD flags;
2478
2479 SecBuffer in_buffers[2];
2480
2481 SecBuffer out_buffers[2];
2482
2483 SecBufferDesc in_desc;
2484
2485 SecBufferDesc out_desc;
2486
2487
2488 for (i = 0; i < 4; i++) {
2489 if (buffers[i].BufferType == SECBUFFER_EXTRA)
2490 break;
2491 }
2492
2493 flags = BB_SCHANNEL_ISC_FLAGS;
2494
2495 in_buffers[0].BufferType = SECBUFFER_TOKEN;
2496 in_buffers[0].pvBuffer = buffers[i].pvBuffer;
2497 in_buffers[0].cbBuffer = buffers[i].cbBuffer;
2498
2499 in_buffers[1].BufferType = SECBUFFER_EMPTY;
2500 in_buffers[1].pvBuffer = NULL;
2501 in_buffers[1].cbBuffer = 0;
2502
2503 out_buffers[0].BufferType = SECBUFFER_TOKEN;
2504 out_buffers[0].pvBuffer = NULL;
2505 out_buffers[0].cbBuffer = 0;
2506
2507 out_buffers[1].BufferType = SECBUFFER_ALERT;
2508 out_buffers[1].pvBuffer = NULL;
2509 out_buffers[1].cbBuffer = 0;
2510
2511 in_desc.ulVersion = SECBUFFER_VERSION;
2512 in_desc.pBuffers = in_buffers;
2513 in_desc.cBuffers = _countof(in_buffers);
2514
2515 out_desc.ulVersion = SECBUFFER_VERSION;
2516 out_desc.pBuffers = out_buffers;
2517 out_desc.cBuffers = _countof(out_buffers);
2518
2519 status = InitializeSecurityContext(&state->cred_handle,
2520 state->initialized ?
2521 &state->ctx_handle : NULL,
2522 state->initialized ? NULL :
2523 state->hostname, flags, 0,
2524 0,
2525 state->initialized ?
2526 &in_desc : NULL, 0,
2527 state->initialized ? NULL :
2528 &state->ctx_handle,
2529 &out_desc, &flags, 0);
2530
2531 if (status != SEC_E_OK) {
2532 bb_error_msg_and_die("schannel: renegotiate failed: (0x%08lx): %s",
2533 status, hresult_to_error_string(status));
2534 }
2535
2536 if (in_buffers[1].BufferType == SECBUFFER_EXTRA) {
2537 memmove(state->in_buffer,
2538 state->in_buffer + (state->in_buffer_size -
2539 in_buffers[1].cbBuffer),
2540 in_buffers[1].cbBuffer);
2541 }
2542
2543 state->out_buffer_used =
2544 state->in_buffer_size - in_buffers[1].cbBuffer;
2545 state->in_buffer_size = in_buffers[1].cbBuffer;
2546
2547 continue;
2548 }
2549 case SEC_E_INCOMPLETE_MESSAGE:{
2550 break;
2551 }
2552 default:{
2553 bb_error_msg_and_die("schannel: DecryptMessage failed: (0x%08lx): %s", status,
2554 hresult_to_error_string(status));
2555 }
2556 }
2557
2558 received =
2559 safe_read(state->ifd,
2560 state->in_buffer + state->in_buffer_size,
2561 sizeof(state->in_buffer) - state->in_buffer_size);
2562 if (received == 0) {
2563 state->closed = 1;
2564 goto Success;
2565 } else if (received < 0) {
2566 bb_error_msg_and_die("schannel: read() failed");
2567 }
2568
2569 state->in_buffer_size += received;
2570 }
2571 }
2572
2573 Success:
2574 return amount_read;
2575}
2576
2577static void tls_write(struct tls_state *state, char *buf, size_t len) {
2578 if (state->closed) {
2579 bb_error_msg_and_die("schannel: attempted to write to a closed connection");
2580 }
2581
2582 while (len > 0) {
2583 unsigned long copy_amount =
2584 min(len, (size_t) state->stream_sizes.cbMaximumMessage);
2585 char *write_buffer = _alloca(sizeof(state->in_buffer));
2586
2587 SECURITY_STATUS status;
2588
2589 SecBuffer buffers[4];
2590
2591 SecBufferDesc desc;
2592
2593 buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
2594 buffers[0].pvBuffer = write_buffer;
2595 buffers[0].cbBuffer = state->stream_sizes.cbHeader;
2596
2597 buffers[1].BufferType = SECBUFFER_DATA;
2598 buffers[1].pvBuffer = write_buffer + state->stream_sizes.cbHeader;
2599 buffers[1].cbBuffer = copy_amount;
2600
2601 buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
2602 buffers[2].pvBuffer =
2603 write_buffer + state->stream_sizes.cbHeader + copy_amount;
2604 buffers[2].cbBuffer = state->stream_sizes.cbTrailer;
2605
2606 buffers[3].BufferType = SECBUFFER_EMPTY;
2607 buffers[3].pvBuffer = NULL;
2608 buffers[3].cbBuffer = 0;
2609
2610 memcpy(buffers[1].pvBuffer, buf, copy_amount);
2611
2612 desc.ulVersion = SECBUFFER_VERSION;
2613 desc.pBuffers = buffers;
2614 desc.cBuffers = _countof(buffers);
2615
2616 status = EncryptMessage(&state->ctx_handle, 0, &desc, 0);
2617 if (status != SEC_E_OK) {
2618 bb_error_msg_and_die("schannel: EncryptMessage failed: (0x%08lx): %s", status,
2619 hresult_to_error_string(status));
2620 }
2621
2622 xwrite(state->ofd, write_buffer,
2623 buffers[0].cbBuffer + buffers[1].cbBuffer +
2624 buffers[2].cbBuffer);
2625
2626 len -= copy_amount;
2627 }
2628}
2629
2630static void tls_disconnect(tls_state_t * state) {
2631 SECURITY_STATUS status;
2632 DWORD token = SCHANNEL_SHUTDOWN;
2633 DWORD flags = BB_SCHANNEL_ISC_FLAGS;
2634
2635 SecBuffer buf_token;
2636
2637 SecBufferDesc buf_token_desc;
2638
2639 SecBuffer in_buffers[2];
2640 SecBuffer out_buffers[2];
2641
2642 SecBufferDesc in_desc;
2643 SecBufferDesc out_desc;
2644
2645 buf_token.BufferType = SECBUFFER_TOKEN;
2646 buf_token.pvBuffer = &token;
2647 buf_token.cbBuffer = sizeof(token);
2648
2649 buf_token_desc.ulVersion = SECBUFFER_VERSION;
2650 buf_token_desc.pBuffers = &buf_token;
2651 buf_token_desc.cBuffers = 1;
2652
2653 ApplyControlToken(&state->ctx_handle, &buf_token_desc);
2654
2655 // attempt to send any final data
2656
2657 in_buffers[0].BufferType = SECBUFFER_TOKEN;
2658 in_buffers[0].pvBuffer = state->in_buffer;
2659 in_buffers[0].cbBuffer = state->in_buffer_size;
2660
2661 in_buffers[1].BufferType = SECBUFFER_EMPTY;
2662 in_buffers[1].pvBuffer = NULL;
2663 in_buffers[1].cbBuffer = 0;
2664
2665 out_buffers[0].BufferType = SECBUFFER_TOKEN;
2666 out_buffers[0].pvBuffer = NULL;
2667 out_buffers[0].cbBuffer = 0;
2668
2669 out_buffers[1].BufferType = SECBUFFER_ALERT;
2670 out_buffers[1].pvBuffer = NULL;
2671 out_buffers[1].cbBuffer = 0;
2672
2673 in_desc.ulVersion = SECBUFFER_VERSION;
2674 in_desc.pBuffers = in_buffers;
2675 in_desc.cBuffers = _countof(in_buffers);
2676
2677 out_desc.ulVersion = SECBUFFER_VERSION;
2678 out_desc.pBuffers = out_buffers;
2679 out_desc.cBuffers = _countof(out_buffers);
2680
2681 status = InitializeSecurityContext(&state->cred_handle,
2682 state->
2683 initialized ? &state->ctx_handle :
2684 NULL,
2685 state->
2686 initialized ? NULL : state->hostname,
2687 flags, 0, 0,
2688 state->initialized ? &in_desc : NULL,
2689 0,
2690 state->
2691 initialized ? NULL :
2692 &state->ctx_handle, &out_desc, &flags,
2693 0);
2694
2695 if (status == SEC_E_OK) {
2696 // attempt to write any extra data
2697 write(state->ofd, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer);
2698 }
2699
2700 DeleteSecurityContext(&state->ctx_handle);
2701 FreeCredentialsHandle(&state->cred_handle);
2702 free(state->hostname);
2703}
2704
2705
2706void FAST_FUNC tls_handshake(tls_state_t * state, const char *hostname) {
2707 SECURITY_STATUS status;
2708 int received;
2709
2710#if ENABLE_FEATURE_TLS_SCHANNEL_1_3
2711 SCH_CREDENTIALS credential = {.dwVersion = SCH_CREDENTIALS_VERSION,
2712 .dwCredFormat = 0,
2713 .cCreds = 0,
2714 .paCred = NULL,
2715 .hRootStore = NULL,
2716 .cMappers = 0,
2717 .aphMappers = NULL,
2718 .dwSessionLifespan = 0,
2719 .dwFlags =
2720 SCH_CRED_AUTO_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
2721 SCH_USE_STRONG_CRYPTO,
2722 .cTlsParameters = 0,
2723 .pTlsParameters = NULL
2724 };
2725#else
2726 SCHANNEL_CRED credential = {.dwVersion = SCHANNEL_CRED_VERSION,
2727 .cCreds = 0,
2728 .paCred = NULL,
2729 .hRootStore = NULL,
2730 .cMappers = 0,
2731 .aphMappers = NULL,
2732 .cSupportedAlgs = 0,
2733 .palgSupportedAlgs = NULL,
2734 .grbitEnabledProtocols =
2735 SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT |
2736 SP_PROT_TLS1_2_CLIENT,
2737 .dwMinimumCipherStrength = 0,
2738 .dwMaximumCipherStrength = 0,
2739 .dwSessionLifespan = 0,
2740 .dwFlags =
2741 SCH_CRED_AUTO_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
2742 SCH_USE_STRONG_CRYPTO,
2743 .dwCredFormat = 0
2744 };
2745#endif
2746
2747 if ((status = AcquireCredentialsHandleA(NULL, (SEC_CHAR *) UNISP_NAME_A,
2748 SECPKG_CRED_OUTBOUND, NULL,
2749 &credential,
2750 NULL, NULL, &state->cred_handle,
2751 NULL)) != SEC_E_OK) {
2752 bb_error_msg_and_die("schannel: AcquireCredentialsHandleA failed: (0x%08lx): %s",
2753 status, hresult_to_error_string(status));
2754 }
2755
2756 state->in_buffer_size = 0;
2757 state->out_buffer_size = 0;
2758 state->out_buffer_used = 0;
2759
2760 state->out_buffer = NULL;
2761
2762 state->hostname = strdup(hostname);
2763
2764 state->initialized = 0;
2765 state->closed = 0;
2766
2767 while (1) {
2768 DWORD flags = BB_SCHANNEL_ISC_FLAGS;
2769
2770 SecBuffer in_buffers[2];
2771 SecBuffer out_buffers[2];
2772
2773 SecBufferDesc in_desc;
2774 SecBufferDesc out_desc;
2775
2776 in_buffers[0].BufferType = SECBUFFER_TOKEN;
2777 in_buffers[0].pvBuffer = state->in_buffer;
2778 in_buffers[0].cbBuffer = state->in_buffer_size;
2779
2780 in_buffers[1].BufferType = SECBUFFER_EMPTY;
2781 in_buffers[1].pvBuffer = NULL;
2782 in_buffers[1].cbBuffer = 0;
2783
2784 out_buffers[0].BufferType = SECBUFFER_TOKEN;
2785 out_buffers[0].pvBuffer = NULL;
2786 out_buffers[0].cbBuffer = 0;
2787
2788 out_buffers[1].BufferType = SECBUFFER_ALERT;
2789 out_buffers[1].pvBuffer = NULL;
2790 out_buffers[1].cbBuffer = 0;
2791
2792 in_desc.ulVersion = SECBUFFER_VERSION;
2793 in_desc.pBuffers = in_buffers;
2794 in_desc.cBuffers = _countof(in_buffers);
2795
2796 out_desc.ulVersion = SECBUFFER_VERSION;
2797 out_desc.pBuffers = out_buffers;
2798 out_desc.cBuffers = _countof(out_buffers);
2799
2800 status = InitializeSecurityContext(&state->cred_handle,
2801 state->
2802 initialized ? &state->ctx_handle :
2803 NULL,
2804 state->
2805 initialized ? NULL :
2806 state->hostname, flags, 0, 0,
2807 state->initialized ? &in_desc :
2808 NULL, 0,
2809 state->initialized ? NULL :
2810 &state->ctx_handle, &out_desc,
2811 &flags, 0);
2812
2813 state->initialized = 1;
2814
2815 if (in_buffers[1].BufferType == SECBUFFER_EXTRA) {
2816 memmove(state->in_buffer,
2817 state->in_buffer + (state->in_buffer_size -
2818 in_buffers[1].cbBuffer),
2819 in_buffers[1].cbBuffer);
2820 state->in_buffer_size = in_buffers[1].cbBuffer;
2821 } else if (status != SEC_E_INCOMPLETE_MESSAGE) {
2822 state->in_buffer_size = 0;
2823 }
2824
2825 switch (status) {
2826 case SEC_E_OK:{
2827 if (out_buffers[0].cbBuffer > 0) {
2828 xwrite(state->ofd, out_buffers[0].pvBuffer,
2829 out_buffers[0].cbBuffer);
2830 FreeContextBuffer(out_buffers[0].pvBuffer);
2831 }
2832 goto Success;
2833 }
2834 case SEC_I_CONTINUE_NEEDED:{
2835 xwrite(state->ofd, out_buffers[0].pvBuffer,
2836 out_buffers[0].cbBuffer);
2837 FreeContextBuffer(out_buffers[0].pvBuffer);
2838 break;
2839 }
2840 case SEC_I_INCOMPLETE_CREDENTIALS:{
2841 // we don't support this
2842 bb_error_msg_and_die("schannel: client certificates not supported");
2843 }
2844 case SEC_E_INCOMPLETE_MESSAGE:{
2845 break;
2846 }
2847 default:{
2848 bb_error_msg_and_die("schannel: handshake failed: (0x%08lx): %s",
2849 status, hresult_to_error_string(status));
2850 }
2851 }
2852
2853 received =
2854 safe_read(state->ifd, state->in_buffer + state->in_buffer_size,
2855 sizeof(state->in_buffer) - state->in_buffer_size);
2856 if (received <= 0) {
2857 bb_error_msg_and_die("schannel: handshake read() failed");
2858 }
2859 state->in_buffer_size += received;
2860 }
2861
2862 Success:
2863 QueryContextAttributes(&state->ctx_handle, SECPKG_ATTR_STREAM_SIZES,
2864 &state->stream_sizes);
2865
2866 //SecPkgContext_ConnectionInfo info;
2867 //QueryContextAttributes(&state->ctx_handle, SECPKG_ATTR_CONNECTION_INFO,
2868 // &info);
2869 //
2870 //fprintf(stderr, "TLS 1.%d\n", (((uint32_t)(8 * sizeof(unsigned long long) - __builtin_clzll((info.dwProtocol)) - 1)) - 7)/2);
2871}
2872
2873void FAST_FUNC tls_run_copy_loop(tls_state_t * tls, unsigned flags) {
2874 char buffer[65536];
2875
2876 struct pollfd pfds[2];
2877
2878 pfds[0].fd = STDIN_FILENO;
2879 pfds[0].events = POLLIN;
2880 pfds[1].fd = tls->ifd;
2881 pfds[1].events = POLLIN;
2882
2883 for (;;) {
2884 int nread;
2885
2886 if (safe_poll(pfds, 2, -1) < 0)
2887 bb_simple_perror_msg_and_die("poll");
2888
2889 if (pfds[0].revents) {
2890 nread = safe_read(STDIN_FILENO, buffer, sizeof(buffer));
2891 if (nread < 1) {
2892 pfds[0].fd = -1;
2893 tls_disconnect(tls);
2894 if (flags & TLSLOOP_EXIT_ON_LOCAL_EOF)
2895 break;
2896 } else {
2897 tls_write(tls, buffer, nread);
2898 }
2899 }
2900 if (pfds[1].revents) {
2901 nread = tls_read(tls, buffer, sizeof(buffer));
2902 if (nread < 1) {
2903 tls_disconnect(tls);
2904 break;
2905 }
2906 xwrite(STDOUT_FILENO, buffer, nread);
2907 }
2908 }
2909}
2910#endif
diff --git a/networking/tls.h b/networking/tls.h
index 0173b87b2..eee5a7617 100644
--- a/networking/tls.h
+++ b/networking/tls.h
@@ -11,6 +11,7 @@
11#include "libbb.h" 11#include "libbb.h"
12 12
13 13
14#if !ENABLE_FEATURE_TLS_SCHANNEL
14/* Config tweaks */ 15/* Config tweaks */
15#define HAVE_NATIVE_INT64 16#define HAVE_NATIVE_INT64
16#undef USE_1024_KEY_SPEED_OPTIMIZATIONS 17#undef USE_1024_KEY_SPEED_OPTIMIZATIONS
@@ -82,10 +83,9 @@ typedef int16_t int16;
82 83
83void tls_get_random(void *buf, unsigned len) FAST_FUNC; 84void tls_get_random(void *buf, unsigned len) FAST_FUNC;
84 85
85void 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))
88void 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
@@ -120,3 +120,4 @@ void curve_P256_compute_pubkey_and_premaster(
120void curve_P256_compute_pubkey_and_premaster_NEW( 120void curve_P256_compute_pubkey_and_premaster_NEW(
121 uint8_t *pubkey2x32, uint8_t *premaster32, 121 uint8_t *pubkey2x32, uint8_t *premaster32,
122 const uint8_t *peerkey2x32) FAST_FUNC; 122 const uint8_t *peerkey2x32) FAST_FUNC;
123#endif
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 }
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 79cef1999..19c961d5c 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -148,10 +148,11 @@ enum {
148 OPT_o = 1 << 12, 148 OPT_o = 1 << 12,
149 OPT_x = 1 << 13, 149 OPT_x = 1 << 13,
150 OPT_f = 1 << 14, 150 OPT_f = 1 << 14,
151 OPT_l = 1 << 15, 151 OPT_m = 1 << 15,
152 OPT_d = 1 << 16, 152 OPT_l = 1 << 16,
153 OPT_d = 1 << 17,
153/* The rest has variable bit positions, need to be clever */ 154/* The rest has variable bit positions, need to be clever */
154 OPTBIT_d = 16, 155 OPTBIT_d = 17,
155 USE_FOR_MMU( OPTBIT_b,) 156 USE_FOR_MMU( OPTBIT_b,)
156 ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) 157 ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
157 IF_FEATURE_UDHCP_PORT( OPTBIT_P,) 158 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
@@ -268,6 +269,23 @@ static void option_to_env(const uint8_t *option, const uint8_t *option_end)
268 //case D6_OPT_SERVERID: 269 //case D6_OPT_SERVERID:
269 case D6_OPT_IA_NA: 270 case D6_OPT_IA_NA:
270 case D6_OPT_IA_PD: 271 case D6_OPT_IA_PD:
272/* 0 1 2 3
273 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
274 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
275 * | OPTION_IA_PD | option-length |
276 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277 * | IAID (4 octets) |
278 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279 * | T1 |
280 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281 * | T2 |
282 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
283 * . .
284 * . IA_PD-options .
285 * . .
286 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
287 */
288 /* recurse to handle "IA_PD-options" field */
271 option_to_env(option + 16, option + 4 + option[3]); 289 option_to_env(option + 16, option + 4 + option[3]);
272 break; 290 break;
273 //case D6_OPT_IA_TA: 291 //case D6_OPT_IA_TA:
@@ -604,6 +622,31 @@ static NOINLINE int send_d6_info_request(void)
604 return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); 622 return d6_mcast_from_client_data_ifindex(&packet, opt_ptr);
605} 623}
606 624
625/*
626 * RFC 3315 10. Identity Association
627 *
628 * An "identity-association" (IA) is a construct through which a server
629 * and a client can identify, group, and manage a set of related IPv6
630 * addresses. Each IA consists of an IAID and associated configuration
631 * information.
632 *
633 * A client must associate at least one distinct IA with each of its
634 * network interfaces for which it is to request the assignment of IPv6
635 * addresses from a DHCP server. The client uses the IAs assigned to an
636 * interface to obtain configuration information from a server for that
637 * interface. Each IA must be associated with exactly one interface.
638 *
639 * The IAID uniquely identifies the IA and must be chosen to be unique
640 * among the IAIDs on the client. The IAID is chosen by the client.
641 * For any given use of an IA by the client, the IAID for that IA MUST
642 * be consistent across restarts of the DHCP client...
643 */
644/* Generate IAID. We base it on our MAC address' last 4 bytes */
645static void generate_iaid(uint8_t *iaid)
646{
647 memcpy(iaid, &client_data.client_mac[2], 4);
648}
649
607/* Multicast a DHCPv6 Solicit packet to the network, with an optionally requested IP. 650/* Multicast a DHCPv6 Solicit packet to the network, with an optionally requested IP.
608 * 651 *
609 * RFC 3315 17.1.1. Creation of Solicit Messages 652 * RFC 3315 17.1.1. Creation of Solicit Messages
@@ -703,7 +746,7 @@ static NOINLINE int send_d6_discover(struct in6_addr *requested_ipv6)
703 client6_data.ia_na = xzalloc(len); 746 client6_data.ia_na = xzalloc(len);
704 client6_data.ia_na->code = D6_OPT_IA_NA; 747 client6_data.ia_na->code = D6_OPT_IA_NA;
705 client6_data.ia_na->len = len - 4; 748 client6_data.ia_na->len = len - 4;
706 *(bb__aliased_uint32_t*)client6_data.ia_na->data = rand(); /* IAID */ 749 generate_iaid(client6_data.ia_na->data); /* IAID */
707 if (requested_ipv6) { 750 if (requested_ipv6) {
708 struct d6_option *iaaddr = (void*)(client6_data.ia_na->data + 4+4+4); 751 struct d6_option *iaaddr = (void*)(client6_data.ia_na->data + 4+4+4);
709 iaaddr->code = D6_OPT_IAADDR; 752 iaaddr->code = D6_OPT_IAADDR;
@@ -721,7 +764,7 @@ static NOINLINE int send_d6_discover(struct in6_addr *requested_ipv6)
721 client6_data.ia_pd = xzalloc(len); 764 client6_data.ia_pd = xzalloc(len);
722 client6_data.ia_pd->code = D6_OPT_IA_PD; 765 client6_data.ia_pd->code = D6_OPT_IA_PD;
723 client6_data.ia_pd->len = len - 4; 766 client6_data.ia_pd->len = len - 4;
724 *(bb__aliased_uint32_t*)client6_data.ia_pd->data = rand(); /* IAID */ 767 generate_iaid(client6_data.ia_pd->data); /* IAID */
725 opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, len); 768 opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, len);
726 } 769 }
727 770
@@ -1131,12 +1174,11 @@ static void client_background(void)
1131//usage:#endif 1174//usage:#endif
1132//usage:#define udhcpc6_trivial_usage 1175//usage:#define udhcpc6_trivial_usage
1133//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R] [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n" 1176//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R] [-t N] [-T SEC] [-A SEC|-n] [-i IFACE] [-s PROG]\n"
1134//usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-ldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..." 1177//usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-mldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..."
1135//usage:#define udhcpc6_full_usage "\n" 1178//usage:#define udhcpc6_full_usage "\n"
1136//usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" 1179//usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")"
1137//usage: "\n -p FILE Create pidfile" 1180//usage: "\n -p FILE Create pidfile"
1138//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC6_DEFAULT_SCRIPT")" 1181//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC6_DEFAULT_SCRIPT")"
1139//usage: "\n -B Request broadcast replies"
1140//usage: "\n -t N Send up to N discover packets" 1182//usage: "\n -t N Send up to N discover packets"
1141//usage: "\n -T SEC Pause between packets (default 3)" 1183//usage: "\n -T SEC Pause between packets (default 3)"
1142//usage: "\n -A SEC Wait if lease is not obtained (default 20)" 1184//usage: "\n -A SEC Wait if lease is not obtained (default 20)"
@@ -1154,6 +1196,7 @@ static void client_background(void)
1154////usage: IF_FEATURE_UDHCPC_ARPING( 1196////usage: IF_FEATURE_UDHCPC_ARPING(
1155////usage: "\n -a Use arping to validate offered address" 1197////usage: "\n -a Use arping to validate offered address"
1156////usage: ) 1198////usage: )
1199//usage: "\n -m Send multicast renew requests rather than unicast ones"
1157//usage: "\n -l Send 'information request' instead of 'solicit'" 1200//usage: "\n -l Send 'information request' instead of 'solicit'"
1158//usage: "\n (used for servers which do not assign IPv6 addresses)" 1201//usage: "\n (used for servers which do not assign IPv6 addresses)"
1159//usage: "\n -r IPv6 Request this address ('no' to not request any IP)" 1202//usage: "\n -r IPv6 Request this address ('no' to not request any IP)"
@@ -1211,7 +1254,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1211 /* Parse command line */ 1254 /* Parse command line */
1212 opt = getopt32long(argv, "^" 1255 opt = getopt32long(argv, "^"
1213 /* O,x: list; -T,-t,-A take numeric param */ 1256 /* O,x: list; -T,-t,-A take numeric param */
1214 "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld" 1257 "i:np:qRr:s:T:+t:+SA:+O:*ox:*fmld"
1215 USE_FOR_MMU("b") 1258 USE_FOR_MMU("b")
1216 ///IF_FEATURE_UDHCPC_ARPING("a") 1259 ///IF_FEATURE_UDHCPC_ARPING("a")
1217 IF_FEATURE_UDHCP_PORT("P:") 1260 IF_FEATURE_UDHCP_PORT("P:")
@@ -1464,7 +1507,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1464 if (opt & OPT_l) 1507 if (opt & OPT_l)
1465 send_d6_info_request(); 1508 send_d6_info_request();
1466 else 1509 else
1467 send_d6_renew(&srv6_buf, requested_ipv6); 1510 send_d6_renew(OPT_m ? NULL : &srv6_buf, requested_ipv6);
1468 timeout = discover_timeout; 1511 timeout = discover_timeout;
1469 packet_num++; 1512 packet_num++;
1470 continue; 1513 continue;
@@ -1606,62 +1649,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1606 case RENEW_REQUESTED: 1649 case RENEW_REQUESTED:
1607 case REBINDING: 1650 case REBINDING:
1608 if (packet.d6_msg_type == D6_MSG_REPLY) { 1651 if (packet.d6_msg_type == D6_MSG_REPLY) {
1609 unsigned start;
1610 uint32_t lease_seconds;
1611 struct d6_option *option;
1612 unsigned address_timeout;
1613 unsigned prefix_timeout;
1614 type_is_ok:
1615 change_listen_mode(LISTEN_NONE);
1616
1617 address_timeout = 0;
1618 prefix_timeout = 0;
1619 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
1620 if (option && (option->data[0] | option->data[1]) != 0) {
1621///FIXME:
1622// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1623// | OPTION_STATUS_CODE | option-len |
1624// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1625// | status-code | |
1626// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1627// . status-message .
1628// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1629// so why do we think it's NAK if data[0] is zero but data[1] is not? That's wrong...
1630// we should also check that option->len is ok (i.e. not 0), right?
1631 /* return to init state */
1632 bb_info_msg("received DHCP NAK (%u)", option->data[4]);
1633 d6_run_script(packet.d6_options,
1634 packet_end, "nak");
1635 if (client_data.state != REQUESTING)
1636 d6_run_script_no_option("deconfig");
1637 sleep(3); /* avoid excessive network traffic */
1638 client_data.state = INIT_SELECTING;
1639 client_data.first_secs = 0; /* make secs field count from 0 */
1640 requested_ipv6 = NULL;
1641 timeout = 0;
1642 packet_num = 0;
1643 continue;
1644 }
1645 option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID);
1646 if (!option) {
1647 bb_simple_info_msg("no server ID, ignoring packet");
1648 continue;
1649 /* still selecting - this server looks bad */
1650 }
1651//Note: we do not bother comparing server IDs in Advertise and Reply msgs.
1652//server_id variable is used solely for creation of proper server_id option
1653//in outgoing packets. (why DHCPv6 even introduced it is a mystery).
1654 free(client6_data.server_id);
1655 client6_data.server_id = option;
1656 if (packet.d6_msg_type == D6_MSG_ADVERTISE) {
1657 /* enter requesting state */
1658 change_listen_mode(LISTEN_RAW);
1659 client_data.state = REQUESTING;
1660 timeout = 0;
1661 packet_num = 0;
1662 continue;
1663 }
1664 /* It's a D6_MSG_REPLY */
1665/* 1652/*
1666 * RFC 3315 18.1.8. Receipt of Reply Messages 1653 * RFC 3315 18.1.8. Receipt of Reply Messages
1667 * 1654 *
@@ -1747,6 +1734,67 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1747 * . . 1734 * . .
1748 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1735 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1749 */ 1736 */
1737 unsigned start;
1738 uint32_t lease_seconds;
1739 struct d6_option *option;
1740 unsigned address_timeout;
1741 unsigned prefix_timeout;
1742 type_is_ok:
1743 change_listen_mode(LISTEN_NONE);
1744
1745 address_timeout = 0;
1746 prefix_timeout = 0;
1747 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
1748 if (option) {
1749// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1750// | OPTION_STATUS_CODE | option-len |
1751// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1752// | status-code | |
1753// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1754// . status-message .
1755// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1756 unsigned len, status;
1757 len = ((unsigned)option->len_hi << 8) + option->len;
1758 if (len < 2) {
1759 bb_simple_error_msg("invalid OPTION_STATUS_CODE, ignoring packet");
1760 continue;
1761 }
1762 status = ((unsigned)option->data[0] << 8) + option->data[1];
1763 if (status != 0) {
1764//TODO: handle status == 5 (UseMulticast)?
1765 /* return to init state */
1766 bb_info_msg("received DHCP NAK: %u '%.*s'", status, len - 2, option->data + 2);
1767 d6_run_script(packet.d6_options, packet_end, "nak");
1768 if (client_data.state != REQUESTING)
1769 d6_run_script_no_option("deconfig");
1770 sleep(3); /* avoid excessive network traffic */
1771 client_data.state = INIT_SELECTING;
1772 client_data.first_secs = 0; /* make secs field count from 0 */
1773 requested_ipv6 = NULL;
1774 timeout = 0;
1775 packet_num = 0;
1776 continue;
1777 }
1778 }
1779 option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID);
1780 if (!option) {
1781 bb_simple_info_msg("no server ID, ignoring packet");
1782 continue;
1783 /* still selecting - this server looks bad */
1784 }
1785//Note: we do not bother comparing server IDs in Advertise and Reply msgs.
1786//server_id variable is used solely for creation of proper server_id option
1787//in outgoing packets. (why DHCPv6 even introduced it is a mystery).
1788 free(client6_data.server_id);
1789 client6_data.server_id = option;
1790 if (packet.d6_msg_type == D6_MSG_ADVERTISE) {
1791 /* enter requesting state */
1792 change_listen_mode(LISTEN_RAW);
1793 client_data.state = REQUESTING;
1794 timeout = 0;
1795 packet_num = 0;
1796 continue;
1797 }
1750 if (option_mask32 & OPT_r) { 1798 if (option_mask32 & OPT_r) {
1751 struct d6_option *iaaddr; 1799 struct d6_option *iaaddr;
1752 1800
@@ -1790,6 +1838,21 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1790 1838
1791 free(client6_data.ia_pd); 1839 free(client6_data.ia_pd);
1792 client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD); 1840 client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD);
1841// 0 1 2 3
1842// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1843// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1844// | OPTION_IA_PD | option-length |
1845// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1846// | IAID (4 octets) |
1847// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1848// | T1 |
1849// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1850// | T2 |
1851// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1852// . .
1853// . IA_PD-options .
1854// . .
1855// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1793 if (!client6_data.ia_pd) { 1856 if (!client6_data.ia_pd) {
1794 bb_info_msg("no %s option%s", "IA_PD", ", ignoring packet"); 1857 bb_info_msg("no %s option%s", "IA_PD", ", ignoring packet");
1795 continue; 1858 continue;
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c
index 142de9b43..1d7541948 100644
--- a/networking/udhcp/d6_packet.c
+++ b/networking/udhcp/d6_packet.c
@@ -153,13 +153,15 @@ int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex(
153 } 153 }
154 setsockopt_reuseaddr(fd); 154 setsockopt_reuseaddr(fd);
155 155
156 memset(&sa, 0, sizeof(sa)); 156 if (src_ipv6) {
157 sa.sin6_family = AF_INET6; 157 memset(&sa, 0, sizeof(sa));
158 sa.sin6_port = htons(source_port); 158 sa.sin6_family = AF_INET6;
159 sa.sin6_addr = *src_ipv6; /* struct copy */ 159 sa.sin6_port = htons(source_port);
160 if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { 160 sa.sin6_addr = *src_ipv6; /* struct copy */
161 msg = "bind(%s)"; 161 if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
162 goto ret_close; 162 msg = "bind(%s)";
163 goto ret_close;
164 }
163 } 165 }
164 166
165 memset(&sa, 0, sizeof(sa)); 167 memset(&sa, 0, sizeof(sa));
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 2904119e5..b9cbd6464 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -575,29 +575,51 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc
575 const uint8_t *chaddr; 575 const uint8_t *chaddr;
576 uint32_t ciaddr; 576 uint32_t ciaddr;
577 577
578 // Was: 578 // Logic:
579 //if (force_broadcast) { /* broadcast */ } 579 //if (force_broadcast) { /* broadcast */ }
580 //else if (dhcp_pkt->ciaddr) { /* unicast to dhcp_pkt->ciaddr */ } 580 //else if (dhcp_pkt->ciaddr) { /* unicast to dhcp_pkt->ciaddr */ }
581 // ^^^ dhcp_pkt->ciaddr comes from client's request packet.
582 // We expect such clients to have an UDP socket listening on that IP.
581 //else if (dhcp_pkt->flags & htons(BROADCAST_FLAG)) { /* broadcast */ } 583 //else if (dhcp_pkt->flags & htons(BROADCAST_FLAG)) { /* broadcast */ }
582 //else { /* unicast to dhcp_pkt->yiaddr */ } 584 //else { /* unicast to dhcp_pkt->yiaddr */ }
583 // But this is wrong: yiaddr is _our_ idea what client's IP is 585 // ^^^ The last case is confusing, but *should* work.
584 // (for example, from lease file). Client may not know that, 586 // It's a case where client have sent a DISCOVER
585 // and may not have UDP socket listening on that IP! 587 // and does not have a kernel UDP socket listening on the IP
586 // We should never unicast to dhcp_pkt->yiaddr! 588 // we are offering in yiaddr (it does not know the IP yet)!
587 // dhcp_pkt->ciaddr, OTOH, comes from client's request packet, 589 // This *should* work because client *should* listen on a raw socket
588 // and can be used. 590 // instead at this time (IOW: it should examine ALL IPv4 packets
589 591 // "by hand", not relying on kernel's UDP stack.)
590 if (force_broadcast 592
591 || (dhcp_pkt->flags & htons(BROADCAST_FLAG)) 593 chaddr = dhcp_pkt->chaddr;
592 || dhcp_pkt->ciaddr == 0 594
595 if (dhcp_pkt->ciaddr == 0
596 || force_broadcast /* sending DHCPNAK pkt? */
593 ) { 597 ) {
594 log1s("broadcasting packet to client"); 598 if (dhcp_pkt->flags & htons(BROADCAST_FLAG)
595 ciaddr = INADDR_BROADCAST; 599 || force_broadcast /* sending DHCPNAK pkt? */
596 chaddr = MAC_BCAST_ADDR; 600 ) {
601// RFC 2131:
602// If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is
603// set, then the server broadcasts DHCPOFFER and DHCPACK messages to
604// 0xffffffff. ...
605// In all cases, when 'giaddr' is zero, the server broadcasts any DHCPNAK
606// messages to 0xffffffff.
607 ciaddr = INADDR_BROADCAST;
608 chaddr = MAC_BCAST_ADDR;
609 log1s("broadcasting packet to client");
610 } else {
611// If the broadcast bit is not set and 'giaddr' is zero and
612// 'ciaddr' is zero, then the server unicasts DHCPOFFER and DHCPACK
613// messages to the client's hardware address and 'yiaddr' address.
614 ciaddr = dhcp_pkt->yiaddr;
615 log1("unicasting packet to client %ciaddr", 'y');
616 }
597 } else { 617 } else {
598 log1s("unicasting packet to client ciaddr"); 618// If the 'giaddr'
619// field is zero and the 'ciaddr' field is nonzero, then the server
620// unicasts DHCPOFFER and DHCPACK messages to the address in 'ciaddr'.
599 ciaddr = dhcp_pkt->ciaddr; 621 ciaddr = dhcp_pkt->ciaddr;
600 chaddr = dhcp_pkt->chaddr; 622 log1("unicasting packet to client %ciaddr", 'c');
601 } 623 }
602 624
603 udhcp_send_raw_packet(dhcp_pkt, 625 udhcp_send_raw_packet(dhcp_pkt,
@@ -624,6 +646,10 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt)
624static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) 646static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast)
625{ 647{
626 if (dhcp_pkt->gateway_nip) 648 if (dhcp_pkt->gateway_nip)
649// RFC 2131:
650// If the 'giaddr' field in a DHCP message from a client is non-zero,
651// the server sends any return messages to the 'DHCP server' port on the
652// BOOTP relay agent whose address appears in 'giaddr'.
627 send_packet_to_relay(dhcp_pkt); 653 send_packet_to_relay(dhcp_pkt);
628 else 654 else
629 send_packet_to_client(dhcp_pkt, force_broadcast); 655 send_packet_to_client(dhcp_pkt, force_broadcast);