fuzz_early_setup:
   23|      2|void fuzz_early_setup(void) {
   24|       |    /* Set stderr to point to normal stderr by default */
   25|       |    fuzz.fake_stderr = stderr;
   26|      2|}
fuzz_common_setup:
   28|      1|void fuzz_common_setup(void) {
   29|      1|	disallow_core();
   30|      1|    fuzz.fuzzing = 1;
   31|      1|    fuzz.wrapfds = 1;
   32|      1|    fuzz.do_jmp = 1;
   33|      1|    fuzz.input = m_malloc(sizeof(buffer));
   34|      1|    _dropbear_log = fuzz_dropbear_log;
   35|      1|    crypto_init();
   36|      1|    fuzz_seed("start", 5);
   37|       |    /* let any messages get flushed */
   38|      1|    setlinebuf(stdout);
   39|       |#if DEBUG_TRACE
   40|       |    if (debug_trace)
   41|       |    {
   42|       |        fprintf(stderr, "Dropbear fuzzer: -v specified, not disabling stderr output\n");
   43|       |    }
   44|       |    else
   45|       |#endif
   46|      1|    if (getenv("DROPBEAR_KEEP_STDERR")) {
  ------------------
  |  Branch (46:9): [True: 0, False: 1]
  ------------------
   47|      0|        fprintf(stderr, "Dropbear fuzzer: DROPBEAR_KEEP_STDERR, not disabling stderr output\n");
   48|      0|    } 
   49|      1|    else 
   50|      1|    {
   51|      1|        fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n");
   52|      1|        fuzz.fake_stderr = fopen("/dev/null", "w");
   53|       |        assert(fuzz.fake_stderr);
  ------------------
  |  Branch (53:9): [True: 0, False: 1]
  |  Branch (53:9): [True: 1, False: 0]
  ------------------
   54|      1|    }
   55|      1|}
fuzz_set_input:
   57|  2.70k|int fuzz_set_input(const uint8_t *Data, size_t Size) {
   58|       |
   59|  2.70k|    fuzz.input->data = (unsigned char*)Data;
   60|  2.70k|    fuzz.input->size = Size;
   61|  2.70k|    fuzz.input->len = Size;
   62|  2.70k|    fuzz.input->pos = 0;
   63|       |
   64|  2.70k|    memset(&ses, 0x0, sizeof(ses));
   65|  2.70k|    memset(&svr_ses, 0x0, sizeof(svr_ses));
   66|  2.70k|    memset(&cli_ses, 0x0, sizeof(cli_ses));
   67|  2.70k|    wrapfd_setup(fuzz.input);
   68|       |    // printhex("input", fuzz.input->data, fuzz.input->len);
   69|       |
   70|  2.70k|    fuzz_seed(fuzz.input->data, MIN(fuzz.input->len, 16));
  ------------------
  |  Branch (70:33): [True: 291, False: 2.41k]
  ------------------
   71|       |
   72|  2.70k|    return DROPBEAR_SUCCESS;
  ------------------
  |  |  111|  2.70k|#define DROPBEAR_SUCCESS 0
  ------------------
   73|  2.70k|}
fuzz_cli_setup:
  112|      1|void fuzz_cli_setup(void) {
  113|      1|    fuzz_common_setup();
  114|       |    
  115|      1|	_dropbear_exit = cli_dropbear_exit;
  116|      1|	_dropbear_log = cli_dropbear_log;
  117|       |
  118|      1|    char *argv[] = { 
  119|      1|		"dbclient",
  120|      1|		"-y",
  121|      1|        "localhost",
  122|      1|        "uptime"
  123|      1|    };
  124|       |
  125|      1|    int argc = sizeof(argv) / sizeof(*argv);
  126|      1|    cli_getopts(argc, argv);
  127|       |
  128|      1|    load_fixed_client_key();
  129|       |    /* Avoid password prompt */
  130|      1|    setenv(DROPBEAR_PASSWORD_ENV, "password", 1);
  ------------------
  |  |  114|      1|#define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD"
  ------------------
  131|      1|}
fuzz_kex_fakealgos:
  197|  1.66k|void fuzz_kex_fakealgos(void) {
  198|  1.66k|    ses.newkeys->recv.crypt_mode = &dropbear_mode_none;
  199|  1.66k|    ses.newkeys->recv.algo_mac = &dropbear_nohash;
  200|  1.66k|}
fuzz_run_client:
  299|  2.70k|int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) {
  300|  2.70k|    static int once = 0;
  301|  2.70k|    if (!once) {
  ------------------
  |  Branch (301:9): [True: 1, False: 2.70k]
  ------------------
  302|      1|        fuzz_cli_setup();
  303|      1|        fuzz.skip_kexmaths = skip_kexmaths;
  304|      1|        once = 1;
  305|      1|    }
  306|       |
  307|  2.70k|    if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|  2.70k|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (307:9): [True: 0, False: 2.70k]
  ------------------
  308|      0|        return 0;
  309|      0|    }
  310|       |
  311|       |    // Allow to proceed sooner
  312|  2.70k|    ses.kexstate.donefirstkex = 1;
  313|       |
  314|  2.70k|    uint32_t wrapseed;
  315|  2.70k|    genrandom((void*)&wrapseed, sizeof(wrapseed));
  316|  2.70k|    wrapfd_setseed(wrapseed);
  317|       |
  318|  2.70k|    int fakesock = wrapfd_new_fuzzinput();
  319|       |
  320|  2.70k|    m_malloc_set_epoch(1);
  321|  2.70k|    fuzz.do_jmp = 1;
  322|  2.70k|    if (setjmp(fuzz.jmp) == 0) {
  ------------------
  |  Branch (322:9): [True: 2.70k, False: 0]
  ------------------
  323|  2.70k|        cli_session(fakesock, fakesock, NULL, 0);
  324|      0|        m_malloc_free_epoch(1, 0);
  325|      0|    } else {
  326|      0|        fuzz.do_jmp = 0;
  327|      0|        m_malloc_free_epoch(1, 1);
  328|      0|        TRACE(("dropbear_exit longjmped"))
  329|       |        /* dropbear_exit jumped here */
  330|      0|    }
  331|       |
  332|      0|    return 0;
  333|  2.70k|}
fuzz_dump:
  345|   109k|void fuzz_dump(const unsigned char* data, size_t len) {
  346|   109k|    if (fuzz.dumping) {
  ------------------
  |  Branch (346:9): [True: 0, False: 109k]
  ------------------
  347|      0|        TRACE(("dump %zu", len))
  348|       |        assert(atomicio(vwrite, fuzz.recv_dumpfd, (void*)data, len) == len);
  ------------------
  |  Branch (348:9): [True: 0, False: 0]
  |  Branch (348:9): [True: 0, False: 0]
  ------------------
  349|      0|    }
  350|   109k|}
fuzz_getpwuid:
  386|      1|struct passwd* fuzz_getpwuid(uid_t uid) {
  387|      1|    if (!fuzz.fuzzing) {
  ------------------
  |  Branch (387:9): [True: 0, False: 1]
  ------------------
  388|      0|        return getpwuid(uid);
  389|      0|    }
  390|      1|    if (uid == pwd_other.pw_uid) {
  ------------------
  |  Branch (390:9): [True: 0, False: 1]
  ------------------
  391|      0|        return &pwd_other;
  392|      0|    }
  393|      1|    if (uid == pwd_root.pw_uid) {
  ------------------
  |  Branch (393:9): [True: 1, False: 0]
  ------------------
  394|      1|        return &pwd_root;
  395|      1|    }
  396|      0|    return NULL;
  397|      1|}
fuzz-common.c:load_fixed_client_key:
  135|      1|static void load_fixed_client_key(void) {
  136|       |
  137|      1|    buffer *b = buf_new(3000);
  138|      1|    sign_key *key;
  139|      1|    enum signkey_type keytype;
  140|       |
  141|      1|    key = new_sign_key();
  142|      1|    keytype = DROPBEAR_SIGNKEY_ANY;
  143|      1|    buf_putbytes(b, keyed25519, keyed25519_len);
  144|      1|    buf_setpos(b, 0);
  145|      1|    if (buf_get_priv_key(b, key, &keytype) == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      1|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (145:9): [True: 0, False: 1]
  ------------------
  146|      0|        dropbear_exit("failed fixed ed25519 hostkey");
  147|      0|    }
  148|      1|    list_append(cli_opts.privkeys, key);
  149|       |
  150|      1|    buf_free(b);
  151|      1|}

fuzz-sshpacketmutator.c:alloc_static_buffers:
  126|      2|static void alloc_static_buffers() {
  127|       |
  128|      2|    int i;
  129|      2|    oup = buf_new(MAX_OUT_SIZE);
  130|      2|    alloc_packetA = buf_new(RECV_MAX_PACKET_LEN);
  ------------------
  |  |  243|      2|#define RECV_MAX_PACKET_LEN (MAX(35000, ((RECV_MAX_PAYLOAD_LEN)+100)))
  ------------------
  |  Branch (130:29): [True: 2, Folded]
  ------------------
  131|      2|    alloc_packetB = buf_new(RECV_MAX_PACKET_LEN);
  ------------------
  |  |  243|      2|#define RECV_MAX_PACKET_LEN (MAX(35000, ((RECV_MAX_PAYLOAD_LEN)+100)))
  ------------------
  |  Branch (131:29): [True: 2, Folded]
  ------------------
  132|       |
  133|  1.00k|    for (i = 0; i < MAX_FUZZ_PACKETS; i++) {
  ------------------
  |  |   20|  1.00k|#define MAX_FUZZ_PACKETS 500
  ------------------
  |  Branch (133:17): [True: 1.00k, False: 2]
  ------------------
  134|  1.00k|        packets1[i] = buf_new(RECV_MAX_PACKET_LEN);
  ------------------
  |  |  243|  1.00k|#define RECV_MAX_PACKET_LEN (MAX(35000, ((RECV_MAX_PAYLOAD_LEN)+100)))
  ------------------
  |  Branch (134:31): [True: 1.00k, Folded]
  ------------------
  135|  1.00k|    }
  136|  1.00k|    for (i = 0; i < MAX_FUZZ_PACKETS; i++) {
  ------------------
  |  |   20|  1.00k|#define MAX_FUZZ_PACKETS 500
  ------------------
  |  Branch (136:17): [True: 1.00k, False: 2]
  ------------------
  137|       |        packets2[i] = buf_new(RECV_MAX_PACKET_LEN);
  ------------------
  |  |  243|  1.00k|#define RECV_MAX_PACKET_LEN (MAX(35000, ((RECV_MAX_PAYLOAD_LEN)+100)))
  ------------------
  |  Branch (137:31): [True: 1.00k, Folded]
  ------------------
  138|  1.00k|    }
  139|      2|}

wrapfd_setup:
   32|  2.70k|void wrapfd_setup(buffer *buf) {
   33|  2.70k|	TRACE(("wrapfd_setup"))
   34|       |
   35|       |	// clean old ones
   36|  2.70k|	int i;
   37|  21.6k|	for (i = 0; i <= wrapfd_maxfd; i++) {
  ------------------
  |  Branch (37:14): [True: 18.9k, False: 2.70k]
  ------------------
   38|  18.9k|		if (wrap_fds[i].mode != UNUSED) {
  ------------------
  |  Branch (38:7): [True: 1.32k, False: 17.5k]
  ------------------
   39|  1.32k|			wrapfd_remove(i);
   40|  1.32k|		}
   41|  18.9k|	}
   42|  2.70k|	wrapfd_maxfd = -1;
   43|       |
   44|  2.70k|	memset(rand_state, 0x0, sizeof(rand_state));
   45|  2.70k|	wrapfd_setseed(50);
   46|  2.70k|	input_buf = buf;
   47|  2.70k|}
wrapfd_setseed:
   49|  5.40k|void wrapfd_setseed(uint32_t seed) {
   50|  5.40k|	memcpy(rand_state, &seed, sizeof(seed));
   51|  5.40k|	nrand48(rand_state);
   52|  5.40k|}
wrapfd_new_fuzzinput:
   54|  2.70k|int wrapfd_new_fuzzinput() {
   55|  2.70k|	if (devnull_fd == -1) {
  ------------------
  |  Branch (55:6): [True: 1, False: 2.70k]
  ------------------
   56|      1|		devnull_fd = open("/dev/null", O_RDONLY);
   57|      1|		assert(devnull_fd != -1);
  ------------------
  |  Branch (57:3): [True: 0, False: 1]
  |  Branch (57:3): [True: 1, False: 0]
  ------------------
   58|      1|	}
   59|       |
   60|  2.70k|	int fd = dup(devnull_fd);
   61|  2.70k|	assert(fd != -1);
  ------------------
  |  Branch (61:2): [True: 0, False: 2.70k]
  |  Branch (61:2): [True: 2.70k, False: 0]
  ------------------
   62|  2.70k|	assert(wrap_fds[fd].mode == UNUSED);
  ------------------
  |  Branch (62:2): [True: 0, False: 2.70k]
  |  Branch (62:2): [True: 2.70k, False: 0]
  ------------------
   63|  2.70k|	wrap_fds[fd].mode = COMMONBUF;
   64|  2.70k|	wrap_fds[fd].closein = 0;
   65|  2.70k|	wrap_fds[fd].closeout = 0;
   66|  2.70k|	wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
  ------------------
  |  Branch (66:17): [True: 2.70k, False: 0]
  ------------------
   67|       |
   68|  2.70k|	return fd;
   69|  2.70k|}
wrapfd_close:
  105|  10.8k|int wrapfd_close(int fd) {
  106|  10.8k|	if (fd >= 0 && fd <= IOWRAP_MAXFD && wrap_fds[fd].mode != UNUSED) {
  ------------------
  |  |    9|  21.7k|#define IOWRAP_MAXFD (FD_SETSIZE-1)
  ------------------
  |  Branch (106:6): [True: 10.8k, False: 0]
  |  Branch (106:17): [True: 10.8k, False: 0]
  |  Branch (106:39): [True: 1.37k, False: 9.49k]
  ------------------
  107|  1.37k|		wrapfd_remove(fd);
  108|  1.37k|		return 0;
  109|  9.49k|	} else {
  110|  9.49k|		return close(fd);
  111|  9.49k|	}
  112|  10.8k|}
wrapfd_read:
  114|   218k|int wrapfd_read(int fd, void *out, size_t count) {
  115|   218k|	size_t maxread;
  116|       |
  117|   218k|	if (!fuzz.wrapfds) {
  ------------------
  |  Branch (117:6): [True: 0, False: 218k]
  ------------------
  118|      0|		return read(fd, out, count);
  119|      0|	}
  120|       |
  121|   218k|	if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) {
  ------------------
  |  |    9|   437k|#define IOWRAP_MAXFD (FD_SETSIZE-1)
  ------------------
  |  Branch (121:6): [True: 0, False: 218k]
  |  Branch (121:16): [True: 0, False: 218k]
  |  Branch (121:37): [True: 0, False: 218k]
  ------------------
  122|       |		/* XXX - assertion failure? */
  123|      0|		TRACE(("Bad read descriptor %d\n", fd))
  124|      0|		errno = EBADF;
  125|      0|		return -1;
  126|      0|	}
  127|       |
  128|   218k|	assert(count != 0);
  ------------------
  |  Branch (128:2): [True: 0, False: 218k]
  |  Branch (128:2): [True: 218k, False: 0]
  ------------------
  129|       |
  130|   218k|	if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) {
  ------------------
  |  Branch (130:6): [True: 0, False: 218k]
  |  Branch (130:30): [True: 16, False: 218k]
  ------------------
  131|     16|		wrap_fds[fd].closein = 1;
  132|     16|		errno = ECONNRESET;
  133|     16|		return -1;
  134|     16|	}
  135|       |
  136|   218k|	if (erand48(rand_state) < CHANCE_INTR) {
  ------------------
  |  Branch (136:6): [True: 412, False: 218k]
  ------------------
  137|    412|		errno = EINTR;
  138|    412|		return -1;
  139|    412|	}
  140|       |
  141|   218k|	if (input_buf && wrap_fds[fd].mode == COMMONBUF) {
  ------------------
  |  Branch (141:6): [True: 218k, False: 0]
  |  Branch (141:19): [True: 218k, False: 0]
  ------------------
  142|   218k|		maxread = MIN(input_buf->len - input_buf->pos, count);
  ------------------
  |  Branch (142:13): [True: 4.60k, False: 213k]
  ------------------
  143|       |		/* returns 0 if buf is EOF, as intended */
  144|   218k|		if (maxread > 0) {
  ------------------
  |  Branch (144:7): [True: 214k, False: 4.11k]
  ------------------
  145|   214k|			maxread = nrand48(rand_state) % maxread + 1;
  146|   214k|		}
  147|   218k|		memcpy(out, buf_getptr(input_buf, maxread), maxread);
  148|   218k|		buf_incrpos(input_buf, maxread);
  149|   218k|		return maxread;
  150|   218k|	}
  151|       |
  152|       |	// return fixed output, of random length
  153|      0|	maxread = MIN(MAX_RANDOM_IN, count);
  ------------------
  |  Branch (153:12): [True: 0, False: 0]
  ------------------
  154|      0|	maxread = nrand48(rand_state) % maxread + 1;
  155|      0|	memset(out, 0xef, maxread);
  156|      0|	return maxread;
  157|   218k|}
wrapfd_select:
  196|   219k|	fd_set *exceptfds, struct timeval *timeout) {
  197|   219k|	int i, nset, sel;
  198|   219k|	int ret = 0;
  199|   219k|	int fdlist[IOWRAP_MAXFD+1];
  200|       |
  201|   219k|	if (!fuzz.wrapfds) {
  ------------------
  |  Branch (201:6): [True: 0, False: 219k]
  ------------------
  202|      0|		return select(nfds, readfds, writefds, exceptfds, timeout);
  203|      0|	}
  204|       |
  205|   219k|	assert(nfds <= IOWRAP_MAXFD+1);
  ------------------
  |  Branch (205:2): [True: 0, False: 219k]
  |  Branch (205:2): [True: 219k, False: 0]
  ------------------
  206|       |
  207|   219k|	if (erand48(rand_state) < CHANCE_INTR) {
  ------------------
  |  Branch (207:6): [True: 249, False: 219k]
  ------------------
  208|    249|		errno = EINTR;
  209|    249|		return -1;
  210|    249|	}
  211|       |
  212|       |	/* read */
  213|   219k|	if (readfds != NULL && erand48(rand_state) < CHANCE_READ1) {
  ------------------
  |  Branch (213:6): [True: 219k, False: 0]
  |  Branch (213:25): [True: 207k, False: 11.5k]
  ------------------
  214|  1.66M|		for (i = 0, nset = 0; i < nfds; i++) {
  ------------------
  |  Branch (214:25): [True: 1.45M, False: 207k]
  ------------------
  215|  1.45M|			if (FD_ISSET(i, readfds)) {
  ------------------
  |  Branch (215:8): [True: 202k, False: 1.25M]
  ------------------
  216|   202k|				assert(wrap_fds[i].mode != UNUSED);
  ------------------
  |  Branch (216:5): [True: 0, False: 202k]
  |  Branch (216:5): [True: 202k, False: 0]
  ------------------
  217|   202k|				fdlist[nset] = i;
  218|   202k|				nset++;
  219|   202k|			}
  220|  1.45M|		}
  221|   207k|		DROPBEAR_FD_ZERO(readfds);
  ------------------
  |  |  106|   207k|#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
  ------------------
  |  Branch (221:3): [Folded, False: 207k]
  ------------------
  222|       |
  223|   207k|		if (nset > 0) {
  ------------------
  |  Branch (223:7): [True: 202k, False: 5.24k]
  ------------------
  224|       |			/* set one */
  225|   202k|			sel = fdlist[nrand48(rand_state) % nset];
  226|   202k|			FD_SET(sel, readfds);
  227|   202k|			ret++;
  228|       |
  229|   202k|			if (erand48(rand_state) < CHANCE_READ2) {
  ------------------
  |  Branch (229:8): [True: 99.1k, False: 103k]
  ------------------
  230|  99.1k|				sel = fdlist[nrand48(rand_state) % nset];
  231|  99.1k|				if (!FD_ISSET(sel, readfds)) {
  ------------------
  |  Branch (231:9): [True: 0, False: 99.1k]
  ------------------
  232|      0|					FD_SET(sel, readfds);
  233|      0|					ret++;
  234|      0|				}
  235|  99.1k|			}
  236|   202k|		}
  237|   207k|	}
  238|       |
  239|       |	/* write */
  240|   219k|	if (writefds != NULL && erand48(rand_state) < CHANCE_WRITE1) {
  ------------------
  |  Branch (240:6): [True: 138k, False: 80.3k]
  |  Branch (240:26): [True: 133k, False: 5.47k]
  ------------------
  241|  1.06M|		for (i = 0, nset = 0; i < nfds; i++) {
  ------------------
  |  Branch (241:25): [True: 933k, False: 133k]
  ------------------
  242|   933k|			if (FD_ISSET(i, writefds)) {
  ------------------
  |  Branch (242:8): [True: 5.27k, False: 928k]
  ------------------
  243|  5.27k|				assert(wrap_fds[i].mode != UNUSED);
  ------------------
  |  Branch (243:5): [True: 0, False: 5.27k]
  |  Branch (243:5): [True: 5.27k, False: 0]
  ------------------
  244|  5.27k|				fdlist[nset] = i;
  245|  5.27k|				nset++;
  246|  5.27k|			}
  247|   933k|		}
  248|   133k|		DROPBEAR_FD_ZERO(writefds);
  ------------------
  |  |  106|   133k|#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
  ------------------
  |  Branch (248:3): [Folded, False: 133k]
  ------------------
  249|       |
  250|       |		/* set one */
  251|   133k|		if (nset > 0) {
  ------------------
  |  Branch (251:7): [True: 5.27k, False: 128k]
  ------------------
  252|  5.27k|			sel = fdlist[nrand48(rand_state) % nset];
  253|  5.27k|			FD_SET(sel, writefds);
  254|  5.27k|			ret++;
  255|       |
  256|  5.27k|			if (erand48(rand_state) < CHANCE_WRITE2) {
  ------------------
  |  Branch (256:8): [True: 1.95k, False: 3.32k]
  ------------------
  257|  1.95k|				sel = fdlist[nrand48(rand_state) % nset];
  258|  1.95k|				if (!FD_ISSET(sel, writefds)) {
  ------------------
  |  Branch (258:9): [True: 0, False: 1.95k]
  ------------------
  259|      0|					FD_SET(sel, writefds);
  260|      0|					ret++;
  261|      0|				}
  262|  1.95k|			}
  263|  5.27k|		}
  264|   133k|	}
  265|   219k|	return ret;
  266|   219k|}
fuzz-wrapfd.c:wrapfd_remove:
   96|  2.70k|static void wrapfd_remove(int fd) {
   97|  2.70k|	TRACE(("wrapfd_remove %d", fd))
   98|  2.70k|	assert(fd >= 0);
  ------------------
  |  Branch (98:2): [True: 0, False: 2.70k]
  |  Branch (98:2): [True: 2.70k, False: 0]
  ------------------
   99|  2.70k|	assert(fd <= IOWRAP_MAXFD);
  ------------------
  |  Branch (99:2): [True: 0, False: 2.70k]
  |  Branch (99:2): [True: 2.70k, False: 0]
  ------------------
  100|  2.70k|	assert(wrap_fds[fd].mode != UNUSED);
  ------------------
  |  Branch (100:2): [True: 0, False: 2.70k]
  |  Branch (100:2): [True: 2.70k, False: 0]
  ------------------
  101|  2.70k|	wrap_fds[fd].mode = UNUSED;
  102|  2.70k|	close(fd);
  103|  2.70k|}

LLVMFuzzerTestOneInput:
    3|  2.70k|int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
    4|  2.70k|	return fuzz_run_client(Data, Size, 1);
    5|  2.70k|}

sha256_init:
  205|  29.2k|{
  206|  29.2k|    LTC_ARGCHK(md != NULL);
  ------------------
  |  |   32|  29.2k|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 29.2k]
  |  |  |  Branch (32:87): [Folded, False: 29.2k]
  |  |  ------------------
  ------------------
  207|       |
  208|  29.2k|    md->sha256.curlen = 0;
  209|  29.2k|    md->sha256.length = 0;
  210|  29.2k|    md->sha256.state[0] = 0x6A09E667UL;
  211|  29.2k|    md->sha256.state[1] = 0xBB67AE85UL;
  212|  29.2k|    md->sha256.state[2] = 0x3C6EF372UL;
  213|  29.2k|    md->sha256.state[3] = 0xA54FF53AUL;
  214|  29.2k|    md->sha256.state[4] = 0x510E527FUL;
  215|  29.2k|    md->sha256.state[5] = 0x9B05688CUL;
  216|  29.2k|    md->sha256.state[6] = 0x1F83D9ABUL;
  217|  29.2k|    md->sha256.state[7] = 0x5BE0CD19UL;
  218|  29.2k|    return CRYPT_OK;
  219|  29.2k|}
sha256_done:
  237|  29.2k|{
  238|  29.2k|    int i;
  239|       |
  240|  29.2k|    LTC_ARGCHK(md  != NULL);
  ------------------
  |  |   32|  29.2k|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 29.2k]
  |  |  |  Branch (32:87): [Folded, False: 29.2k]
  |  |  ------------------
  ------------------
  241|  29.2k|    LTC_ARGCHK(out != NULL);
  ------------------
  |  |   32|  29.2k|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 29.2k]
  |  |  |  Branch (32:87): [Folded, False: 29.2k]
  |  |  ------------------
  ------------------
  242|       |
  243|  29.2k|    if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
  ------------------
  |  Branch (243:9): [True: 0, False: 29.2k]
  ------------------
  244|      0|       return CRYPT_INVALID_ARG;
  245|      0|    }
  246|       |
  247|       |
  248|       |    /* increase the length of the message */
  249|  29.2k|    md->sha256.length += md->sha256.curlen * 8;
  250|       |
  251|       |    /* append the '1' bit */
  252|  29.2k|    md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
  253|       |
  254|       |    /* if the length is currently above 56 bytes we append zeros
  255|       |     * then compress.  Then we can fall back to padding zeros and length
  256|       |     * encoding like normal.
  257|       |     */
  258|  29.2k|    if (md->sha256.curlen > 56) {
  ------------------
  |  Branch (258:9): [True: 0, False: 29.2k]
  ------------------
  259|      0|        while (md->sha256.curlen < 64) {
  ------------------
  |  Branch (259:16): [True: 0, False: 0]
  ------------------
  260|      0|            md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
  261|      0|        }
  262|      0|        sha256_compress(md, md->sha256.buf);
  263|      0|        md->sha256.curlen = 0;
  264|      0|    }
  265|       |
  266|       |    /* pad upto 56 bytes of zeroes */
  267|   608k|    while (md->sha256.curlen < 56) {
  ------------------
  |  Branch (267:12): [True: 578k, False: 29.2k]
  ------------------
  268|   578k|        md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
  269|   578k|    }
  270|       |
  271|       |    /* store length */
  272|  29.2k|    STORE64H(md->sha256.length, md->sha256.buf+56);
  ------------------
  |  |  101|  29.2k|#define STORE64H(x, y)                          \
  |  |  102|  29.2k|do { ulong64 __t = __builtin_bswap64 ((x));     \
  |  |  103|  29.2k|      XMEMCPY ((y), &__t, 8); } while(0)
  |  |  ------------------
  |  |  |  |   39|  29.2k|#define XMEMCPY  memcpy
  |  |  ------------------
  |  |  |  Branch (103:39): [Folded, False: 29.2k]
  |  |  ------------------
  ------------------
  273|  29.2k|    sha256_compress(md, md->sha256.buf);
  274|       |
  275|       |    /* copy output */
  276|   263k|    for (i = 0; i < 8; i++) {
  ------------------
  |  Branch (276:17): [True: 233k, False: 29.2k]
  ------------------
  277|   233k|        STORE32H(md->sha256.state[i], out+(4*i));
  ------------------
  |  |   62|   233k|#define STORE32H(x, y)                          \
  |  |   63|   233k|do { ulong32 __t = __builtin_bswap32 ((x));     \
  |  |   64|   233k|      XMEMCPY ((y), &__t, 4); } while(0)
  |  |  ------------------
  |  |  |  |   39|   233k|#define XMEMCPY  memcpy
  |  |  ------------------
  |  |  |  Branch (64:39): [Folded, False: 233k]
  |  |  ------------------
  ------------------
  278|   233k|    }
  279|       |#ifdef LTC_CLEAN_STACK
  280|       |    zeromem(md, sizeof(hash_state));
  281|       |#endif
  282|  29.2k|    return CRYPT_OK;
  283|  29.2k|}
sha256.c:sha256_compress:
   71|  29.2k|{
   72|  29.2k|    ulong32 S[8], W[64], t0, t1;
   73|  29.2k|#ifdef LTC_SMALL_CODE
   74|  29.2k|    ulong32 t;
   75|  29.2k|#endif
   76|  29.2k|    int i;
   77|       |
   78|       |    /* copy state into S */
   79|   263k|    for (i = 0; i < 8; i++) {
  ------------------
  |  Branch (79:17): [True: 233k, False: 29.2k]
  ------------------
   80|   233k|        S[i] = md->sha256.state[i];
   81|   233k|    }
   82|       |
   83|       |    /* copy the state into 512-bits into W[0..15] */
   84|   497k|    for (i = 0; i < 16; i++) {
  ------------------
  |  Branch (84:17): [True: 467k, False: 29.2k]
  ------------------
   85|   467k|        LOAD32H(W[i], buf + (4*i));
  ------------------
  |  |   66|   467k|#define LOAD32H(x, y)                           \
  |  |   67|   467k|do { XMEMCPY (&(x), (y), 4);                    \
  |  |  ------------------
  |  |  |  |   39|   467k|#define XMEMCPY  memcpy
  |  |  ------------------
  |  |   68|   467k|      (x) = __builtin_bswap32 ((x)); } while(0)
  |  |  ------------------
  |  |  |  Branch (68:46): [Folded, False: 467k]
  |  |  ------------------
  ------------------
   86|   467k|    }
   87|       |
   88|       |    /* fill W[16..63] */
   89|  1.43M|    for (i = 16; i < 64; i++) {
  ------------------
  |  Branch (89:18): [True: 1.40M, False: 29.2k]
  ------------------
   90|  1.40M|        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
  ------------------
  |  |   63|  1.40M|#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
  |  |  ------------------
  |  |  |  |   58|  1.40M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  ------------------
  |  |  |  |  |  |  283|  1.40M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  284|  1.40M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  285|  1.40M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  286|  1.40M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  287|  1.40M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  288|  1.40M|            "I" (i)); \
  |  |  |  |  |  |  289|  1.40M|            __RORc_tmp; \
  |  |  |  |  |  |  290|  1.40M|   })
  |  |  |  |  ------------------
  |  |  ------------------
  |  |               #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
  |  |  ------------------
  |  |  |  |   58|  1.40M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  ------------------
  |  |  |  |  |  |  283|  1.40M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  284|  1.40M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  285|  1.40M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  286|  1.40M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  287|  1.40M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  288|  1.40M|            "I" (i)); \
  |  |  |  |  |  |  289|  1.40M|            __RORc_tmp; \
  |  |  |  |  |  |  290|  1.40M|   })
  |  |  |  |  ------------------
  |  |  ------------------
  |  |               #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
  |  |  ------------------
  |  |  |  |   59|  1.40M|#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
  |  |  ------------------
  ------------------
                      W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
  ------------------
  |  |   62|  1.40M|#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
  |  |  ------------------
  |  |  |  |   58|  1.40M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  ------------------
  |  |  |  |  |  |  283|  1.40M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  284|  1.40M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  285|  1.40M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  286|  1.40M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  287|  1.40M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  288|  1.40M|            "I" (i)); \
  |  |  |  |  |  |  289|  1.40M|            __RORc_tmp; \
  |  |  |  |  |  |  290|  1.40M|   })
  |  |  |  |  ------------------
  |  |  ------------------
  |  |               #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
  |  |  ------------------
  |  |  |  |   58|  1.40M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  ------------------
  |  |  |  |  |  |  283|  1.40M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  284|  1.40M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  285|  1.40M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  286|  1.40M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  287|  1.40M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  288|  1.40M|            "I" (i)); \
  |  |  |  |  |  |  289|  1.40M|            __RORc_tmp; \
  |  |  |  |  |  |  290|  1.40M|   })
  |  |  |  |  ------------------
  |  |  ------------------
  |  |               #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
  |  |  ------------------
  |  |  |  |   59|  1.40M|#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
  |  |  ------------------
  ------------------
   91|  1.40M|    }
   92|       |
   93|       |    /* Compress */
   94|  29.2k|#ifdef LTC_SMALL_CODE
   95|  29.2k|#define RND(a,b,c,d,e,f,g,h,i)                         \
   96|  29.2k|     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
   97|  29.2k|     t1 = Sigma0(a) + Maj(a, b, c);                    \
   98|  29.2k|     d += t0;                                          \
   99|  29.2k|     h  = t0 + t1;
  100|       |
  101|  1.90M|     for (i = 0; i < 64; ++i) {
  ------------------
  |  Branch (101:18): [True: 1.87M, False: 29.2k]
  ------------------
  102|  1.87M|         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
  ------------------
  |  |   96|  1.87M|     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
  |  |  ------------------
  |  |  |  |   61|  1.87M|#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
  |  |  |  |  ------------------
  |  |  |  |  |  |   58|  1.87M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  283|  1.87M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  |  |  284|  1.87M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  |  |  285|  1.87M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  |  |  286|  1.87M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  |  |  287|  1.87M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  |  |  288|  1.87M|            "I" (i)); \
  |  |  |  |  |  |  |  |  289|  1.87M|            __RORc_tmp; \
  |  |  |  |  |  |  |  |  290|  1.87M|   })
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |               #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
  |  |  |  |  ------------------
  |  |  |  |  |  |   58|  1.87M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  283|  1.87M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  |  |  284|  1.87M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  |  |  285|  1.87M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  |  |  286|  1.87M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  |  |  287|  1.87M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  |  |  288|  1.87M|            "I" (i)); \
  |  |  |  |  |  |  |  |  289|  1.87M|            __RORc_tmp; \
  |  |  |  |  |  |  |  |  290|  1.87M|   })
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |               #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
  |  |  |  |  ------------------
  |  |  |  |  |  |   58|  1.87M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  283|  1.87M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  |  |  284|  1.87M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  |  |  285|  1.87M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  |  |  286|  1.87M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  |  |  287|  1.87M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  |  |  288|  1.87M|            "I" (i)); \
  |  |  |  |  |  |  |  |  289|  1.87M|            __RORc_tmp; \
  |  |  |  |  |  |  |  |  290|  1.87M|   })
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |                    t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
  |  |  ------------------
  |  |  |  |   56|  1.87M|#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
  |  |  ------------------
  |  |   97|  1.87M|     t1 = Sigma0(a) + Maj(a, b, c);                    \
  |  |  ------------------
  |  |  |  |   60|  1.87M|#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
  |  |  |  |  ------------------
  |  |  |  |  |  |   58|  1.87M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  283|  1.87M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  |  |  284|  1.87M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  |  |  285|  1.87M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  |  |  286|  1.87M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  |  |  287|  1.87M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  |  |  288|  1.87M|            "I" (i)); \
  |  |  |  |  |  |  |  |  289|  1.87M|            __RORc_tmp; \
  |  |  |  |  |  |  |  |  290|  1.87M|   })
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |               #define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
  |  |  |  |  ------------------
  |  |  |  |  |  |   58|  1.87M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  283|  1.87M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  |  |  284|  1.87M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  |  |  285|  1.87M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  |  |  286|  1.87M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  |  |  287|  1.87M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  |  |  288|  1.87M|            "I" (i)); \
  |  |  |  |  |  |  |  |  289|  1.87M|            __RORc_tmp; \
  |  |  |  |  |  |  |  |  290|  1.87M|   })
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |               #define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
  |  |  |  |  ------------------
  |  |  |  |  |  |   58|  1.87M|#define S(x, n)         RORc((x),(n))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  283|  1.87M|#define RORc(word,i) ({ \
  |  |  |  |  |  |  |  |  284|  1.87M|   ulong32 __RORc_tmp = (word); \
  |  |  |  |  |  |  |  |  285|  1.87M|   __asm__ ("rorl %2, %0" : \
  |  |  |  |  |  |  |  |  286|  1.87M|            "=r" (__RORc_tmp) : \
  |  |  |  |  |  |  |  |  287|  1.87M|            "0" (__RORc_tmp), \
  |  |  |  |  |  |  |  |  288|  1.87M|            "I" (i)); \
  |  |  |  |  |  |  |  |  289|  1.87M|            __RORc_tmp; \
  |  |  |  |  |  |  |  |  290|  1.87M|   })
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |                    t1 = Sigma0(a) + Maj(a, b, c);                    \
  |  |  ------------------
  |  |  |  |   57|  1.87M|#define Maj(x,y,z)      (((x | y) & z) | (x & y))
  |  |  ------------------
  |  |   98|  1.87M|     d += t0;                                          \
  |  |   99|  1.87M|     h  = t0 + t1;
  ------------------
  103|  1.87M|         t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
  104|  1.87M|         S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
  105|  1.87M|     }
  106|       |#else
  107|       |#define RND(a,b,c,d,e,f,g,h,i,ki)                    \
  108|       |     t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \
  109|       |     t1 = Sigma0(a) + Maj(a, b, c);                  \
  110|       |     d += t0;                                        \
  111|       |     h  = t0 + t1;
  112|       |
  113|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
  114|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
  115|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
  116|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
  117|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
  118|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
  119|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
  120|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
  121|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
  122|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
  123|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
  124|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
  125|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
  126|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
  127|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
  128|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
  129|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
  130|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
  131|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
  132|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
  133|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
  134|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
  135|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
  136|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
  137|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
  138|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
  139|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
  140|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
  141|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
  142|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
  143|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
  144|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
  145|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
  146|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
  147|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
  148|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
  149|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
  150|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
  151|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
  152|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
  153|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
  154|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
  155|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
  156|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
  157|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
  158|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
  159|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
  160|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
  161|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
  162|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
  163|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
  164|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
  165|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
  166|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
  167|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
  168|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
  169|       |    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
  170|       |    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
  171|       |    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
  172|       |    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
  173|       |    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
  174|       |    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
  175|       |    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
  176|       |    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
  177|       |
  178|       |#undef RND
  179|       |
  180|       |#endif
  181|       |
  182|       |    /* feedback */
  183|   263k|    for (i = 0; i < 8; i++) {
  ------------------
  |  Branch (183:17): [True: 233k, False: 29.2k]
  ------------------
  184|   233k|        md->sha256.state[i] = md->sha256.state[i] + S[i];
  185|   233k|    }
  186|  29.2k|    return CRYPT_OK;
  187|  29.2k|}

sha256_process:
  491|  58.4k|int func_name (hash_state * md, const unsigned char *in, unsigned long inlen)               \
  492|  58.4k|{                                                                                           \
  493|  58.4k|    unsigned long n;                                                                        \
  494|  58.4k|    int           err;                                                                      \
  495|  58.4k|    LTC_ARGCHK(md != NULL);                                                                 \
  ------------------
  |  |   32|  58.4k|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 58.4k]
  |  |  |  Branch (32:87): [Folded, False: 58.4k]
  |  |  ------------------
  ------------------
  496|  58.4k|    LTC_ARGCHK(in != NULL);                                                                 \
  ------------------
  |  |   32|  58.4k|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 58.4k]
  |  |  |  Branch (32:87): [Folded, False: 58.4k]
  |  |  ------------------
  ------------------
  497|  58.4k|    if (md-> state_var .curlen > sizeof(md-> state_var .buf)) {                             \
  ------------------
  |  Branch (497:9): [True: 0, False: 58.4k]
  ------------------
  498|      0|       return CRYPT_INVALID_ARG;                                                            \
  499|      0|    }                                                                                       \
  500|  58.4k|    if ((md-> state_var .length + inlen) < md-> state_var .length) {                        \
  ------------------
  |  Branch (500:9): [True: 0, False: 58.4k]
  ------------------
  501|      0|      return CRYPT_HASH_OVERFLOW;                                                           \
  502|      0|    }                                                                                       \
  503|   116k|    while (inlen > 0) {                                                                     \
  ------------------
  |  Branch (503:12): [True: 58.4k, False: 58.4k]
  ------------------
  504|  58.4k|        if (md-> state_var .curlen == 0 && inlen >= block_size) {                           \
  ------------------
  |  Branch (504:13): [True: 29.2k, False: 29.2k]
  |  Branch (504:44): [True: 0, False: 29.2k]
  ------------------
  505|      0|           if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) {               \
  ------------------
  |  Branch (505:16): [True: 0, False: 0]
  ------------------
  506|      0|              return err;                                                                   \
  507|      0|           }                                                                                \
  508|      0|           md-> state_var .length += block_size * 8;                                        \
  509|      0|           in             += block_size;                                                    \
  510|      0|           inlen          -= block_size;                                                    \
  511|  58.4k|        } else {                                                                            \
  512|  58.4k|           n = MIN(inlen, (block_size - md-> state_var .curlen));                           \
  ------------------
  |  |  425|  58.4k|   #define MIN(x, y) ( ((x)<(y))?(x):(y) )
  |  |  ------------------
  |  |  |  Branch (425:24): [True: 58.4k, False: 0]
  |  |  ------------------
  ------------------
  513|  58.4k|           XMEMCPY(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n);             \
  ------------------
  |  |   39|  58.4k|#define XMEMCPY  memcpy
  ------------------
  514|  58.4k|           md-> state_var .curlen += n;                                                     \
  515|  58.4k|           in             += n;                                                             \
  516|  58.4k|           inlen          -= n;                                                             \
  517|  58.4k|           if (md-> state_var .curlen == block_size) {                                      \
  ------------------
  |  Branch (517:16): [True: 0, False: 58.4k]
  ------------------
  518|      0|              if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) {            \
  ------------------
  |  Branch (518:19): [True: 0, False: 0]
  ------------------
  519|      0|                 return err;                                                                \
  520|      0|              }                                                                             \
  521|      0|              md-> state_var .length += 8*block_size;                                       \
  522|      0|              md-> state_var .curlen = 0;                                                   \
  523|      0|           }                                                                                \
  524|  58.4k|       }                                                                                    \
  525|  58.4k|    }                                                                                       \
  526|  58.4k|    return CRYPT_OK;                                                                        \
  527|  58.4k|}

register_cipher:
   22|      1|{
   23|      1|   int x;
   24|       |
   25|      1|   LTC_ARGCHK(cipher != NULL);
  ------------------
  |  |   32|      1|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 1]
  |  |  |  Branch (32:87): [Folded, False: 1]
  |  |  ------------------
  ------------------
   26|       |
   27|       |   /* is it already registered? */
   28|      1|   LTC_MUTEX_LOCK(&ltc_cipher_mutex);
   29|      6|   for (x = 0; x < TAB_SIZE; x++) {
  ------------------
  |  |   14|      6|#define TAB_SIZE      5
  ------------------
  |  Branch (29:16): [True: 5, False: 1]
  ------------------
   30|      5|       if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
  ------------------
  |  Branch (30:12): [True: 0, False: 5]
  |  Branch (30:49): [True: 0, False: 0]
  ------------------
   31|      0|          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
   32|      0|          return x;
   33|      0|       }
   34|      5|   }
   35|       |
   36|       |   /* find a blank spot */
   37|      1|   for (x = 0; x < TAB_SIZE; x++) {
  ------------------
  |  |   14|      1|#define TAB_SIZE      5
  ------------------
  |  Branch (37:16): [True: 1, False: 0]
  ------------------
   38|      1|       if (cipher_descriptor[x].name == NULL) {
  ------------------
  |  Branch (38:12): [True: 1, False: 0]
  ------------------
   39|      1|          XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor));
  ------------------
  |  |   39|      1|#define XMEMCPY  memcpy
  ------------------
   40|      1|          LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
   41|      1|          return x;
   42|      1|       }
   43|      1|   }
   44|       |
   45|       |   /* no spot */
   46|      0|   LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);
   47|      0|   return -1;
   48|      1|}

register_hash:
   22|      3|{
   23|      3|   int x;
   24|       |
   25|      3|   LTC_ARGCHK(hash != NULL);
  ------------------
  |  |   32|      3|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 3]
  |  |  |  Branch (32:87): [Folded, False: 3]
  |  |  ------------------
  ------------------
   26|       |
   27|       |   /* is it already registered? */
   28|      3|   LTC_MUTEX_LOCK(&ltc_hash_mutex);
   29|     18|   for (x = 0; x < TAB_SIZE; x++) {
  ------------------
  |  |   14|     18|#define TAB_SIZE      5
  ------------------
  |  Branch (29:16): [True: 15, False: 3]
  ------------------
   30|     15|       if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
  ------------------
  |  |   45|     15|#define XMEMCMP  memcmp
  ------------------
  |  Branch (30:12): [True: 0, False: 15]
  ------------------
   31|      0|          LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
   32|      0|          return x;
   33|      0|       }
   34|     15|   }
   35|       |
   36|       |   /* find a blank spot */
   37|      6|   for (x = 0; x < TAB_SIZE; x++) {
  ------------------
  |  |   14|      6|#define TAB_SIZE      5
  ------------------
  |  Branch (37:16): [True: 6, False: 0]
  ------------------
   38|      6|       if (hash_descriptor[x].name == NULL) {
  ------------------
  |  Branch (38:12): [True: 3, False: 3]
  ------------------
   39|      3|          XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor));
  ------------------
  |  |   39|      3|#define XMEMCPY  memcpy
  ------------------
   40|      3|          LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
   41|      3|          return x;
   42|      3|       }
   43|      6|   }
   44|       |
   45|       |   /* no spot */
   46|      0|   LTC_MUTEX_UNLOCK(&ltc_hash_mutex);
   47|      0|   return -1;
   48|      3|}

register_prng:
   22|      1|{
   23|      1|   int x;
   24|       |
   25|      1|   LTC_ARGCHK(prng != NULL);
  ------------------
  |  |   32|      1|#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
  |  |  ------------------
  |  |  |  Branch (32:32): [True: 0, False: 1]
  |  |  |  Branch (32:87): [Folded, False: 1]
  |  |  ------------------
  ------------------
   26|       |
   27|       |   /* is it already registered? */
   28|      1|   LTC_MUTEX_LOCK(&ltc_prng_mutex);
   29|      6|   for (x = 0; x < TAB_SIZE; x++) {
  ------------------
  |  |   14|      6|#define TAB_SIZE      5
  ------------------
  |  Branch (29:16): [True: 5, False: 1]
  ------------------
   30|      5|       if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
  ------------------
  |  |   45|      5|#define XMEMCMP  memcmp
  ------------------
  |  Branch (30:12): [True: 0, False: 5]
  ------------------
   31|      0|          LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
   32|      0|          return x;
   33|      0|       }
   34|      5|   }
   35|       |
   36|       |   /* find a blank spot */
   37|      1|   for (x = 0; x < TAB_SIZE; x++) {
  ------------------
  |  |   14|      1|#define TAB_SIZE      5
  ------------------
  |  Branch (37:16): [True: 1, False: 0]
  ------------------
   38|      1|       if (prng_descriptor[x].name == NULL) {
  ------------------
  |  Branch (38:12): [True: 1, False: 0]
  ------------------
   39|      1|          XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor));
  ------------------
  |  |   39|      1|#define XMEMCPY  memcpy
  ------------------
   40|      1|          LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
   41|      1|          return x;
   42|      1|       }
   43|      1|   }
   44|       |
   45|       |   /* no spot */
   46|      0|   LTC_MUTEX_UNLOCK(&ltc_prng_mutex);
   47|      0|   return -1;
   48|      1|}

mp_rand_source:
   10|      1|{
   11|       |   /* Dropbear, don't reset to platform if source==NULL */
   12|      1|   s_mp_rand_source = source;
   13|      1|}

buf_new:
   41|  70.0k|buffer* buf_new(unsigned int size) {
   42|  70.0k|	buffer* buf;
   43|  70.0k|	if (size > BUF_MAX_SIZE) {
  ------------------
  |  |   35|  70.0k|#define BUF_MAX_SIZE 1000000000
  ------------------
  |  Branch (43:6): [True: 0, False: 70.0k]
  ------------------
   44|      0|		dropbear_exit("buf->size too big");
   45|      0|	}
   46|       |
   47|  70.0k|	buf = (buffer*)m_malloc(sizeof(buffer)+size);
   48|  70.0k|	buf->data = (unsigned char*)buf + sizeof(buffer);
   49|  70.0k|	buf->size = size;
   50|  70.0k|	return buf;
   51|  70.0k|}
buf_free:
   54|  56.2k|void buf_free(buffer* buf) {
   55|       |	m_free(buf);
  ------------------
  |  |   24|  56.2k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 56.2k]
  |  |  ------------------
  ------------------
   56|  56.2k|}
buf_burn_free:
   59|  8.31k|void buf_burn_free(buffer* buf) {
   60|  8.31k|	m_burn(buf->data, buf->size);
   61|       |	m_free(buf);
  ------------------
  |  |   24|  8.31k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 8.31k]
  |  |  ------------------
  ------------------
   62|  8.31k|}
buf_resize:
   67|  2.69k|buffer* buf_resize(buffer *buf, unsigned int newsize) {
   68|  2.69k|	if (newsize > BUF_MAX_SIZE) {
  ------------------
  |  |   35|  2.69k|#define BUF_MAX_SIZE 1000000000
  ------------------
  |  Branch (68:6): [True: 0, False: 2.69k]
  ------------------
   69|      0|		dropbear_exit("buf->size too big");
   70|      0|	}
   71|       |
   72|  2.69k|	buf = m_realloc(buf, sizeof(buffer)+newsize);
   73|  2.69k|	buf->data = (unsigned char*)buf + sizeof(buffer);
   74|  2.69k|	buf->size = newsize;
   75|  2.69k|	buf->len = MIN(newsize, buf->len);
  ------------------
  |  Branch (75:13): [True: 0, False: 2.69k]
  ------------------
   76|       |	buf->pos = MIN(newsize, buf->pos);
  ------------------
  |  Branch (76:13): [True: 0, False: 2.69k]
  ------------------
   77|  2.69k|	return buf;
   78|  2.69k|}
buf_newcopy:
   82|  6.17k|buffer* buf_newcopy(const buffer* buf) {
   83|       |	
   84|  6.17k|	buffer* ret;
   85|       |
   86|  6.17k|	ret = buf_new(buf->len);
   87|  6.17k|	ret->len = buf->len;
   88|  6.17k|	if (buf->len > 0) {
  ------------------
  |  Branch (88:6): [True: 6.17k, False: 0]
  ------------------
   89|  6.17k|		memcpy(ret->data, buf->data, buf->len);
   90|  6.17k|	}
   91|  6.17k|	return ret;
   92|  6.17k|}
buf_setlen:
   95|   109k|void buf_setlen(buffer* buf, unsigned int len) {
   96|   109k|	if (len > buf->size) {
  ------------------
  |  Branch (96:6): [True: 0, False: 109k]
  ------------------
   97|      0|		dropbear_exit("Bad buf_setlen");
   98|      0|	}
   99|   109k|	buf->len = len;
  100|       |	buf->pos = MIN(buf->pos, buf->len);
  ------------------
  |  Branch (100:13): [True: 85.1k, False: 24.5k]
  ------------------
  101|   109k|}
buf_incrlen:
  104|   110k|void buf_incrlen(buffer* buf, unsigned int incr) {
  105|   110k|	if (incr > BUF_MAX_INCR || buf->len + incr > buf->size) {
  ------------------
  |  |   34|   221k|#define BUF_MAX_INCR 1000000000
  ------------------
  |  Branch (105:6): [True: 0, False: 110k]
  |  Branch (105:29): [True: 0, False: 110k]
  ------------------
  106|      0|		dropbear_exit("Bad buf_incrlen");
  107|      0|	}
  108|   110k|	buf->len += incr;
  109|   110k|}
buf_setpos:
  111|   399k|void buf_setpos(buffer* buf, unsigned int pos) {
  112|       |
  113|   399k|	if (pos > buf->len) {
  ------------------
  |  Branch (113:6): [True: 0, False: 399k]
  ------------------
  114|      0|		dropbear_exit("Bad buf_setpos");
  115|      0|	}
  116|   399k|	buf->pos = pos;
  117|   399k|}
buf_incrwritepos:
  120|   363k|void buf_incrwritepos(buffer* buf, unsigned int incr) {
  121|   363k|	if (incr > BUF_MAX_INCR || buf->pos + incr > buf->size) {
  ------------------
  |  |   34|   727k|#define BUF_MAX_INCR 1000000000
  ------------------
  |  Branch (121:6): [True: 0, False: 363k]
  |  Branch (121:29): [True: 0, False: 363k]
  ------------------
  122|      0|		dropbear_exit("Bad buf_incrwritepos");
  123|      0|	}
  124|   363k|	buf->pos += incr;
  125|   363k|	if (buf->pos > buf->len) {
  ------------------
  |  Branch (125:6): [True: 269k, False: 94.1k]
  ------------------
  126|   269k|		buf->len = buf->pos;
  127|   269k|	}
  128|   363k|}
buf_incrpos:
  131|   427k|void buf_incrpos(buffer* buf, unsigned int incr) {
  132|   427k|	if (incr > BUF_MAX_INCR 
  ------------------
  |  |   34|   854k|#define BUF_MAX_INCR 1000000000
  ------------------
  |  Branch (132:6): [True: 50, False: 427k]
  ------------------
  133|   427k|		|| (buf->pos + incr) > buf->len) {
  ------------------
  |  Branch (133:6): [True: 113, False: 426k]
  ------------------
  134|    163|		dropbear_exit("Bad buf_incrpos");
  135|    163|	}
  136|   426k|	buf->pos += incr;
  137|   426k|}
buf_decrpos:
  140|      1|void buf_decrpos(buffer* buf, unsigned int decr) {
  141|      1|	if (decr > buf->pos) {
  ------------------
  |  Branch (141:6): [True: 0, False: 1]
  ------------------
  142|      0|		dropbear_exit("Bad buf_decrpos");
  143|      0|	}
  144|      1|	buf->pos -= decr;
  145|      1|}
buf_getbyte:
  148|  91.3k|unsigned char buf_getbyte(buffer* buf) {
  149|       |
  150|       |	/* This check is really just ==, but the >= allows us to check for the
  151|       |	 * bad case of pos > len, which should _never_ happen. */
  152|  91.3k|	if (buf->pos >= buf->len) {
  ------------------
  |  Branch (152:6): [True: 1, False: 91.3k]
  ------------------
  153|      1|		dropbear_exit("Bad buf_getbyte");
  154|      1|	}
  155|  91.3k|	return buf->data[buf->pos++];
  156|  91.3k|}
buf_getbool:
  159|  2.89k|unsigned char buf_getbool(buffer* buf) {
  160|       |
  161|  2.89k|	unsigned char b;
  162|  2.89k|	b = buf_getbyte(buf);
  163|  2.89k|	if (b != 0)
  ------------------
  |  Branch (163:6): [True: 954, False: 1.94k]
  ------------------
  164|    954|		b = 1;
  165|  2.89k|	return b;
  166|  2.89k|}
buf_putbyte:
  169|   110k|void buf_putbyte(buffer* buf, unsigned char val) {
  170|       |
  171|   110k|	if (buf->pos >= buf->len) {
  ------------------
  |  Branch (171:6): [True: 89.4k, False: 21.1k]
  ------------------
  172|  89.4k|		buf_incrlen(buf, 1);
  173|  89.4k|	}
  174|   110k|	buf->data[buf->pos] = val;
  175|   110k|	buf->pos++;
  176|   110k|}
buf_getptr:
  180|   519k|unsigned char* buf_getptr(const buffer* buf, unsigned int len) {
  181|       |
  182|   519k|	if (len > BUF_MAX_INCR || buf->pos + len > buf->len) {
  ------------------
  |  |   34|  1.03M|#define BUF_MAX_INCR 1000000000
  ------------------
  |  Branch (182:6): [True: 0, False: 519k]
  |  Branch (182:28): [True: 269, False: 519k]
  ------------------
  183|    269|		dropbear_exit("Bad buf_getptr");
  184|    269|	}
  185|   519k|	return &buf->data[buf->pos];
  186|   519k|}
buf_getwriteptr:
  190|   428k|unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len) {
  191|       |
  192|   428k|	if (len > BUF_MAX_INCR || buf->pos + len > buf->size) {
  ------------------
  |  |   34|   857k|#define BUF_MAX_INCR 1000000000
  ------------------
  |  Branch (192:6): [True: 0, False: 428k]
  |  Branch (192:28): [True: 0, False: 428k]
  ------------------
  193|      0|		dropbear_exit("Bad buf_getwriteptr");
  194|      0|	}
  195|   428k|	return &buf->data[buf->pos];
  196|   428k|}
buf_getstring:
  201|  23.0k|char* buf_getstring(buffer* buf, unsigned int *retlen) {
  202|       |
  203|  23.0k|	unsigned int len;
  204|  23.0k|	char* ret;
  205|  23.0k|	void* src = NULL;
  206|  23.0k|	len = buf_getint(buf);
  207|  23.0k|	if (len > MAX_STRING_LEN) {
  ------------------
  |  |  253|  23.0k|#define MAX_STRING_LEN (MAX(MAX_CMD_LEN, 2400)) /* Sun SSH needs 2400 for algos,
  ------------------
  |  Branch (207:6): [True: 56, False: 23.0k]
  |  Branch (207:12): [True: 22.9k, Folded]
  ------------------
  208|     56|		dropbear_exit("String too long");
  209|     56|	}
  210|       |
  211|  23.0k|	if (retlen != NULL) {
  ------------------
  |  Branch (211:6): [True: 22.4k, False: 548]
  ------------------
  212|  22.4k|		*retlen = len;
  213|  22.4k|	}
  214|  23.0k|	src = buf_getptr(buf, len);
  215|  23.0k|	ret = m_malloc(len+1);
  216|  23.0k|	memcpy(ret, src, len);
  217|  23.0k|	buf_incrpos(buf, len);
  218|  23.0k|	ret[len] = '\0';
  219|       |
  220|  23.0k|	return ret;
  221|  23.0k|}
buf_getbuf:
  251|    102|buffer * buf_getbuf(buffer *buf) {
  252|    102|	return buf_getstringbuf_int(buf, 1);
  253|    102|}
buf_eatstring:
  266|  8.36k|void buf_eatstring(buffer *buf) {
  267|       |
  268|  8.36k|	buf_incrpos( buf, buf_getint(buf) );
  269|  8.36k|}
buf_getint:
  272|  71.7k|unsigned int buf_getint(buffer* buf) {
  273|  71.7k|	unsigned int ret;
  274|       |
  275|  71.7k|	LOAD32H(ret, buf_getptr(buf, 4));
  ------------------
  |  |   66|  71.7k|#define LOAD32H(x, y)                           \
  |  |   67|  71.7k|do { XMEMCPY (&(x), (y), 4);                    \
  |  |  ------------------
  |  |  |  |   39|  71.7k|#define XMEMCPY  memcpy
  |  |  ------------------
  |  |   68|  71.7k|      (x) = __builtin_bswap32 ((x)); } while(0)
  |  |  ------------------
  |  |  |  Branch (68:46): [Folded, False: 71.7k]
  |  |  ------------------
  ------------------
  276|  71.7k|	buf_incrpos(buf, 4);
  277|  71.7k|	return ret;
  278|  71.7k|}
buf_putint:
  281|   106k|void buf_putint(buffer* buf, int unsigned val) {
  282|       |
  283|   106k|	STORE32H(val, buf_getwriteptr(buf, 4));
  ------------------
  |  |   62|   106k|#define STORE32H(x, y)                          \
  |  |   63|   106k|do { ulong32 __t = __builtin_bswap32 ((x));     \
  |  |   64|   106k|      XMEMCPY ((y), &__t, 4); } while(0)
  |  |  ------------------
  |  |  |  |   39|   106k|#define XMEMCPY  memcpy
  |  |  ------------------
  |  |  |  Branch (64:39): [Folded, False: 106k]
  |  |  ------------------
  ------------------
  284|   106k|	buf_incrwritepos(buf, 4);
  285|       |
  286|   106k|}
buf_putstring:
  289|  17.6k|void buf_putstring(buffer* buf, const char* str, unsigned int len) {
  290|       |	
  291|  17.6k|	buf_putint(buf, len);
  292|  17.6k|	buf_putbytes(buf, (const unsigned char*)str, len);
  293|       |
  294|  17.6k|}
buf_putbytes:
  303|   125k|void buf_putbytes(buffer *buf, const unsigned char *bytes, unsigned int len) {
  304|   125k|	memcpy(buf_getwriteptr(buf, len), bytes, len);
  305|   125k|	buf_incrwritepos(buf, len);
  306|   125k|}
buffer.c:buf_getstringbuf_int:
  224|    102|static buffer * buf_getstringbuf_int(buffer *buf, int incllen) {
  225|    102|	buffer *ret = NULL;
  226|    102|	unsigned int len = buf_getint(buf);
  227|    102|	int extra = 0;
  228|    102|	if (len > MAX_STRING_LEN) {
  ------------------
  |  |  253|    102|#define MAX_STRING_LEN (MAX(MAX_CMD_LEN, 2400)) /* Sun SSH needs 2400 for algos,
  ------------------
  |  Branch (228:6): [True: 36, False: 66]
  |  Branch (228:12): [True: 99, Folded]
  ------------------
  229|     36|		dropbear_exit("String too long");
  230|     36|	}
  231|     66|	if (incllen) {
  ------------------
  |  Branch (231:6): [True: 63, False: 3]
  ------------------
  232|     63|		extra = 4;
  233|     63|	}
  234|     66|	ret = buf_new(len+extra);
  235|     66|	if (incllen) {
  ------------------
  |  Branch (235:6): [True: 63, False: 3]
  ------------------
  236|     63|		buf_putint(ret, len);
  237|     63|	}
  238|     66|	memcpy(buf_getwriteptr(ret, len), buf_getptr(buf, len), len);
  239|     66|	buf_incrpos(buf, len);
  240|     66|	buf_incrlen(ret, len);
  241|     66|	buf_setpos(ret, 0);
  242|     66|	return ret;
  243|    102|}

cbuf_new:
   31|    647|circbuffer * cbuf_new(unsigned int size) {
   32|       |
   33|    647|	circbuffer *cbuf = NULL;
   34|       |
   35|    647|	if (size > MAX_CBUF_SIZE) {
  ------------------
  |  |   29|    647|#define MAX_CBUF_SIZE 100000000
  ------------------
  |  Branch (35:6): [True: 0, False: 647]
  ------------------
   36|      0|		dropbear_exit("Bad cbuf size");
   37|      0|	}
   38|       |
   39|    647|	cbuf = (circbuffer*)m_malloc(sizeof(circbuffer));
   40|       |	/* data is malloced on first write */
   41|    647|	cbuf->data = NULL;
   42|    647|	cbuf->used = 0;
   43|    647|	cbuf->readpos = 0;
   44|    647|	cbuf->writepos = 0;
   45|    647|	cbuf->size = size;
   46|       |
   47|    647|	return cbuf;
   48|    647|}
cbuf_free:
   50|    647|void cbuf_free(circbuffer * cbuf) {
   51|       |
   52|    647|	if (cbuf->data) {
  ------------------
  |  Branch (52:6): [True: 0, False: 647]
  ------------------
   53|      0|		m_burn(cbuf->data, cbuf->size);
   54|      0|		m_free(cbuf->data);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
   55|      0|	}
   56|       |	m_free(cbuf);
  ------------------
  |  |   24|    647|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 647]
  |  |  ------------------
  ------------------
   57|    647|}

cli-agentfwd.c:new_agent_chan:
   78|    194|static int new_agent_chan(struct Channel * channel) {
   79|       |
   80|    194|	int fd = -1;
   81|       |
   82|    194|	if (!cli_opts.agent_fwd)
  ------------------
  |  Branch (82:6): [True: 194, False: 0]
  ------------------
   83|    194|		return SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
  ------------------
  |  |   33|    194|#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED    1
  ------------------
   84|       |
   85|      0|	fd = connect_agent();
   86|      0|	if (fd < 0) {
  ------------------
  |  Branch (86:6): [True: 0, False: 0]
  ------------------
   87|      0|		return SSH_OPEN_CONNECT_FAILED;
  ------------------
  |  |   34|      0|#define SSH_OPEN_CONNECT_FAILED                 2
  ------------------
   88|      0|	}
   89|       |
   90|      0|	setnonblocking(fd);
   91|       |
   92|      0|	ses.maxfd = MAX(ses.maxfd, fd);
  ------------------
  |  Branch (92:14): [True: 0, False: 0]
  ------------------
   93|       |
   94|      0|	channel->readfd = fd;
   95|      0|	channel->writefd = fd;
   96|      0|	channel->bidir_fd = 1;
   97|       |
   98|      0|	return 0;
   99|      0|}

cli_auth_getmethods:
   36|    591|void cli_auth_getmethods() {
   37|    591|	TRACE(("enter cli_auth_getmethods"))
   38|    591|	CHECKCLEARTOWRITE();
   39|    591|	buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
  ------------------
  |  |   42|    591|#define SSH_MSG_USERAUTH_REQUEST            50
  ------------------
   40|    591|	buf_putstring(ses.writepayload, cli_opts.username,
   41|    591|			strlen(cli_opts.username));
   42|    591|	buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
  ------------------
  |  |  110|    591|#define SSH_SERVICE_CONNECTION "ssh-connection"
  ------------------
   43|    591|			SSH_SERVICE_CONNECTION_LEN);
  ------------------
  |  |  111|    591|#define SSH_SERVICE_CONNECTION_LEN 14
  ------------------
   44|    591|	buf_putstring(ses.writepayload, "none", 4); /* 'none' method */
   45|       |
   46|    591|	encrypt_packet();
   47|       |
   48|       |#if DROPBEAR_CLI_IMMEDIATE_AUTH
   49|       |	/* We can't haven't two auth requests in-flight with delayed zlib mode
   50|       |	since if the first one succeeds then the remote side will 
   51|       |	expect the second one to be compressed. 
   52|       |	Race described at
   53|       |	http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/zlib-openssh.html
   54|       |	*/
   55|       |	if (ses.keys->trans.algo_comp != DROPBEAR_COMP_ZLIB_DELAY) {
   56|       |		ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
   57|       |#if DROPBEAR_USE_PASSWORD_ENV
   58|       |		if (getenv(DROPBEAR_PASSWORD_ENV)) {
   59|       |			ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
   60|       |		}
   61|       |#endif
   62|       |		if (cli_auth_try() == DROPBEAR_SUCCESS) {
   63|       |			TRACE(("skipped initial none auth query"))
   64|       |			/* Note that there will be two auth responses in-flight */
   65|       |			cli_ses.ignore_next_auth_response = 1;
   66|       |		}
   67|       |	}
   68|       |#endif
   69|    591|	TRACE(("leave cli_auth_getmethods"))
   70|    591|}
recv_msg_userauth_banner:
   72|    911|void recv_msg_userauth_banner() {
   73|       |
   74|    911|	char* banner = NULL;
   75|    911|	unsigned int bannerlen;
   76|    911|	unsigned int i, linecount;
   77|    911|	int truncated = 0;
   78|       |
   79|    911|	TRACE(("enter recv_msg_userauth_banner"))
   80|    911|	if (ses.authstate.authdone) {
  ------------------
  |  Branch (80:6): [True: 195, False: 716]
  ------------------
   81|    195|		TRACE(("leave recv_msg_userauth_banner: banner after auth done"))
   82|    195|		return;
   83|    195|	}
   84|       |
   85|    716|	if (cli_opts.quiet) {
  ------------------
  |  Branch (85:6): [True: 0, False: 716]
  ------------------
   86|      0|		TRACE(("not showing banner"))
   87|      0|		return;
   88|      0|	}
   89|       |
   90|    716|	banner = buf_getstring(ses.payload, &bannerlen);
   91|    716|	buf_eatstring(ses.payload); /* The language string */
   92|       |
   93|    716|	if (bannerlen > MAX_BANNER_SIZE) {
  ------------------
  |  |   72|    716|#define MAX_BANNER_SIZE 2050 /* this is 25*80 chars, any more is foolish */
  ------------------
  |  Branch (93:6): [True: 49, False: 667]
  ------------------
   94|     49|		TRACE(("recv_msg_userauth_banner: bannerlen too long: %d", bannerlen))
   95|     49|		truncated = 1;
   96|    667|	} else {
   97|    667|		cleantext(banner);
   98|       |
   99|       |		/* Limit to 24 lines */
  100|    667|		linecount = 1;
  101|  25.1k|		for (i = 0; i < bannerlen; i++) {
  ------------------
  |  Branch (101:15): [True: 24.6k, False: 461]
  ------------------
  102|  24.6k|			if (banner[i] == '\n') {
  ------------------
  |  Branch (102:8): [True: 4.28k, False: 20.3k]
  ------------------
  103|  4.28k|				if (linecount >= MAX_BANNER_LINES) {
  ------------------
  |  |   73|  4.28k|#define MAX_BANNER_LINES 20 /* How many lines the client will display */
  ------------------
  |  Branch (103:9): [True: 206, False: 4.07k]
  ------------------
  104|    206|					banner[i] = '\0';
  105|    206|					truncated = 1;
  106|    206|					break;
  107|    206|				}
  108|  4.07k|				linecount++;
  109|  4.07k|			}
  110|  24.6k|		}
  111|    667|		fprintf(stderr, "%s\n", banner);
  ------------------
  |  |  100|    667|#define stderr (fuzz.fake_stderr)
  ------------------
  112|    667|	}
  113|       |
  114|    716|	if (truncated) {
  ------------------
  |  Branch (114:6): [True: 255, False: 461]
  ------------------
  115|    255|		fprintf(stderr, "[Banner from the server is too long]\n");
  ------------------
  |  |  100|    255|#define stderr (fuzz.fake_stderr)
  ------------------
  116|    255|	}
  117|       |
  118|       |	m_free(banner);
  ------------------
  |  |   24|    716|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 716]
  |  |  ------------------
  ------------------
  119|    716|	TRACE(("leave recv_msg_userauth_banner"))
  120|    716|}
recv_msg_userauth_specific_60:
  127|      2|void recv_msg_userauth_specific_60() {
  128|       |
  129|      2|#if DROPBEAR_CLI_PUBKEY_AUTH
  130|      2|	if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
  ------------------
  |  |  103|      2|#define AUTH_TYPE_PUBKEY    (1 << 1)
  ------------------
  |  Branch (130:6): [True: 0, False: 2]
  ------------------
  131|      0|		recv_msg_userauth_pk_ok();
  132|      0|		return;
  133|      0|	}
  134|      2|#endif
  135|       |
  136|      2|#if DROPBEAR_CLI_INTERACT_AUTH
  137|      2|	if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT) {
  ------------------
  |  |  105|      2|#define AUTH_TYPE_INTERACT  (1 << 3)
  ------------------
  |  Branch (137:6): [True: 0, False: 2]
  ------------------
  138|      0|		recv_msg_userauth_info_request();
  139|      0|		return;
  140|      0|	}
  141|      2|#endif
  142|       |
  143|      2|#if DROPBEAR_CLI_PASSWORD_AUTH
  144|      2|	if (cli_ses.lastauthtype == AUTH_TYPE_PASSWORD) {
  ------------------
  |  |  104|      2|#define AUTH_TYPE_PASSWORD  (1 << 2)
  ------------------
  |  Branch (144:6): [True: 0, False: 2]
  ------------------
  145|       |		/* Eventually there could be proper password-changing
  146|       |		 * support. However currently few servers seem to
  147|       |		 * implement it, and password auth is last-resort
  148|       |		 * regardless - keyboard-interactive is more likely
  149|       |		 * to be used anyway. */
  150|      0|		dropbear_close("Your password has expired.");
  151|      0|	}
  152|      2|#endif
  153|       |
  154|      2|	dropbear_exit("Unexpected userauth packet");
  155|      2|}
recv_msg_userauth_failure:
  157|    513|void recv_msg_userauth_failure() {
  158|       |
  159|    513|	char * methods = NULL;
  160|    513|	char * tok = NULL;
  161|    513|	unsigned int methlen = 0;
  162|    513|	unsigned int partial = 0;
  163|    513|	unsigned int i = 0;
  164|    513|	int allow_pw_auth = 1;
  165|       |
  166|    513|	TRACE(("<- MSG_USERAUTH_FAILURE"))
  167|    513|	TRACE(("enter recv_msg_userauth_failure"))
  168|       |
  169|    513|	if (ses.authstate.authdone) {
  ------------------
  |  Branch (169:6): [True: 197, False: 316]
  ------------------
  170|    197|		TRACE(("leave recv_msg_userauth_failure, already authdone."))
  171|    197|		return;
  172|    197|	}
  173|       |
  174|    316|	if (cli_ses.state != USERAUTH_REQ_SENT) {
  ------------------
  |  Branch (174:6): [True: 1, False: 315]
  ------------------
  175|       |		/* Perhaps we should be more fatal? */
  176|      1|		dropbear_exit("Unexpected userauth failure");
  177|      1|	}
  178|       |
  179|       |	/* Password authentication is only allowed in batch mode
  180|       |	 * when a password can be provided non-interactively */
  181|    315|	if (cli_opts.batch_mode && !getenv(DROPBEAR_PASSWORD_ENV)) {
  ------------------
  |  |  114|      0|#define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD"
  ------------------
  |  Branch (181:6): [True: 0, False: 315]
  |  Branch (181:29): [True: 0, False: 0]
  ------------------
  182|      0|		allow_pw_auth = 0;
  183|      0|	}
  184|    315|	allow_pw_auth &= cli_opts.password_authentication;
  185|       |
  186|       |	/* When DROPBEAR_CLI_IMMEDIATE_AUTH is set there will be an initial response for 
  187|       |	the "none" auth request, and then a response to the immediate auth request. 
  188|       |	We need to be careful handling them. */
  189|    315|	if (cli_ses.ignore_next_auth_response) {
  ------------------
  |  Branch (189:6): [True: 0, False: 315]
  ------------------
  190|      0|		cli_ses.state = USERAUTH_REQ_SENT;
  191|      0|		cli_ses.ignore_next_auth_response = 0;
  192|      0|		TRACE(("leave recv_msg_userauth_failure, ignored response, state set to USERAUTH_REQ_SENT"));
  193|      0|		return;
  194|    315|	} else  {
  195|    315|#if DROPBEAR_CLI_PUBKEY_AUTH
  196|       |		/* If it was a pubkey auth request, we should cross that key 
  197|       |		 * off the list. */
  198|    315|		if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
  ------------------
  |  |  103|    315|#define AUTH_TYPE_PUBKEY    (1 << 1)
  ------------------
  |  Branch (198:7): [True: 0, False: 315]
  ------------------
  199|      0|			cli_pubkeyfail();
  200|      0|		}
  201|    315|#endif
  202|       |
  203|    315|#if DROPBEAR_CLI_INTERACT_AUTH
  204|       |		/* If we get a failure message for keyboard interactive without
  205|       |		 * receiving any request info packet, then we don't bother trying
  206|       |		 * keyboard interactive again */
  207|    315|		if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT
  ------------------
  |  |  105|    630|#define AUTH_TYPE_INTERACT  (1 << 3)
  ------------------
  |  Branch (207:7): [True: 0, False: 315]
  ------------------
  208|      0|				&& !cli_ses.interact_request_received) {
  ------------------
  |  Branch (208:8): [True: 0, False: 0]
  ------------------
  209|      0|			TRACE(("setting auth_interact_failed = 1"))
  210|      0|			cli_ses.auth_interact_failed = 1;
  211|      0|		}
  212|    315|#endif
  213|    315|		cli_ses.state = USERAUTH_FAIL_RCVD;
  214|    315|		cli_ses.lastauthtype = AUTH_TYPE_NONE;
  ------------------
  |  |  102|    315|#define AUTH_TYPE_NONE      1
  ------------------
  215|    315|	}
  216|       |
  217|    315|	methods = buf_getstring(ses.payload, &methlen);
  218|       |
  219|    315|	partial = buf_getbool(ses.payload);
  220|       |
  221|    315|	if (partial) {
  ------------------
  |  Branch (221:6): [True: 248, False: 67]
  ------------------
  222|    248|		dropbear_log(LOG_INFO, "Authentication partially succeeded, more attempts required");
  223|    248|	} else {
  224|     67|		ses.authstate.failcount++;
  225|     67|	}
  226|       |
  227|    315|	TRACE(("Methods (len %d): '%s'", methlen, methods))
  228|       |
  229|    315|	ses.authstate.authdone=0;
  230|    315|	ses.authstate.authtypes=0;
  231|       |
  232|       |	/* Split with nulls rather than commas */
  233|  38.5k|	for (i = 0; i < methlen; i++) {
  ------------------
  |  Branch (233:14): [True: 38.2k, False: 315]
  ------------------
  234|  38.2k|		if (methods[i] == ',') {
  ------------------
  |  Branch (234:7): [True: 901, False: 37.3k]
  ------------------
  235|    901|			methods[i] = '\0';
  236|    901|		}
  237|  38.2k|	}
  238|       |
  239|    315|	tok = methods; /* tok stores the next method we'll compare */
  240|  38.8k|	for (i = 0; i <= methlen; i++) {
  ------------------
  |  Branch (240:14): [True: 38.5k, False: 315]
  ------------------
  241|  38.5k|		if (methods[i] == '\0') {
  ------------------
  |  Branch (241:7): [True: 9.36k, False: 29.1k]
  ------------------
  242|  9.36k|			TRACE(("auth method '%s'", tok))
  243|  9.36k|#if DROPBEAR_CLI_PUBKEY_AUTH
  244|  9.36k|			if (strncmp(AUTH_METHOD_PUBKEY, tok,
  ------------------
  |  |  109|  9.36k|#define AUTH_METHOD_PUBKEY "publickey"
  ------------------
  |  Branch (244:8): [True: 199, False: 9.16k]
  ------------------
  245|  9.36k|				AUTH_METHOD_PUBKEY_LEN) == 0) {
  ------------------
  |  |  110|  9.36k|#define AUTH_METHOD_PUBKEY_LEN 9
  ------------------
  246|    199|				ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
  ------------------
  |  |  103|    199|#define AUTH_TYPE_PUBKEY    (1 << 1)
  ------------------
  247|    199|			}
  248|  9.36k|#endif
  249|  9.36k|#if DROPBEAR_CLI_INTERACT_AUTH
  250|  9.36k|			if (allow_pw_auth
  ------------------
  |  Branch (250:8): [True: 9.36k, False: 0]
  ------------------
  251|  9.36k|				&& strncmp(AUTH_METHOD_INTERACT, tok, AUTH_METHOD_INTERACT_LEN) == 0) {
  ------------------
  |  |  113|  9.36k|#define AUTH_METHOD_INTERACT "keyboard-interactive"
  ------------------
              				&& strncmp(AUTH_METHOD_INTERACT, tok, AUTH_METHOD_INTERACT_LEN) == 0) {
  ------------------
  |  |  114|  9.36k|#define AUTH_METHOD_INTERACT_LEN 20
  ------------------
  |  Branch (251:8): [True: 195, False: 9.16k]
  ------------------
  252|    195|				ses.authstate.authtypes |= AUTH_TYPE_INTERACT;
  ------------------
  |  |  105|    195|#define AUTH_TYPE_INTERACT  (1 << 3)
  ------------------
  253|    195|			}
  254|  9.36k|#endif
  255|  9.36k|#if DROPBEAR_CLI_PASSWORD_AUTH
  256|  9.36k|			if (allow_pw_auth
  ------------------
  |  Branch (256:8): [True: 9.36k, False: 0]
  ------------------
  257|  9.36k|				&& strncmp(AUTH_METHOD_PASSWORD, tok, AUTH_METHOD_PASSWORD_LEN) == 0) {
  ------------------
  |  |  111|  9.36k|#define AUTH_METHOD_PASSWORD "password"
  ------------------
              				&& strncmp(AUTH_METHOD_PASSWORD, tok, AUTH_METHOD_PASSWORD_LEN) == 0) {
  ------------------
  |  |  112|  9.36k|#define AUTH_METHOD_PASSWORD_LEN 8
  ------------------
  |  Branch (257:8): [True: 207, False: 9.15k]
  ------------------
  258|    207|				ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
  ------------------
  |  |  104|    207|#define AUTH_TYPE_PASSWORD  (1 << 2)
  ------------------
  259|    207|			}
  260|  9.36k|#endif
  261|  9.36k|			tok = &methods[i+1]; /* Must make sure we don't use it after the
  262|       |									last loop, since it'll point to something
  263|       |									undefined */
  264|  9.36k|		}
  265|  38.5k|	}
  266|       |
  267|    315|	m_free(methods);
  ------------------
  |  |   24|    315|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 315]
  |  |  ------------------
  ------------------
  268|       |		
  269|    315|	TRACE(("leave recv_msg_userauth_failure"))
  270|    315|}
recv_msg_userauth_success:
  272|  1.63k|void recv_msg_userauth_success() {
  273|       |	/* This function can validly get called multiple times
  274|       |	if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
  275|       |
  276|  1.63k|	DEBUG1(("received msg_userauth_success"))
  277|  1.63k|	if (cli_opts.disable_trivial_auth && cli_ses.is_trivial_auth) {
  ------------------
  |  Branch (277:6): [True: 0, False: 1.63k]
  |  Branch (277:39): [True: 0, False: 0]
  ------------------
  278|      0|		dropbear_exit("trivial authentication not allowed");
  279|      0|	}
  280|       |	/* Note: in delayed-zlib mode, setting authdone here 
  281|       |	 * will enable compression in the transport layer */
  282|  1.63k|	ses.authstate.authdone = 1;
  283|  1.63k|	cli_ses.state = USERAUTH_SUCCESS_RCVD;
  284|  1.63k|	cli_ses.lastauthtype = AUTH_TYPE_NONE;
  ------------------
  |  |  102|  1.63k|#define AUTH_TYPE_NONE      1
  ------------------
  285|       |
  286|  1.63k|#if DROPBEAR_CLI_PUBKEY_AUTH
  287|  1.63k|	cli_auth_pubkey_cleanup();
  288|  1.63k|#endif
  289|  1.63k|}

cli_auth_pubkey_cleanup:
  283|  1.63k|void cli_auth_pubkey_cleanup() {
  284|       |
  285|  1.63k|#if DROPBEAR_CLI_AGENTFWD
  286|  1.63k|	m_close(cli_opts.agent_fd);
  287|  1.63k|	cli_opts.agent_fd = -1;
  288|  1.63k|#endif
  289|       |
  290|  1.63k|	while (cli_opts.privkeys->first) {
  ------------------
  |  Branch (290:9): [True: 1, False: 1.63k]
  ------------------
  291|      1|		sign_key * key = list_remove(cli_opts.privkeys->first);
  292|      1|		sign_key_free(key);
  293|      1|	}
  294|  1.63k|}

recv_msg_channel_extended_data:
   34|     42|void recv_msg_channel_extended_data() {
   35|       |
   36|     42|	struct Channel *channel;
   37|     42|	unsigned int datatype;
   38|       |
   39|     42|	TRACE(("enter recv_msg_channel_extended_data"))
   40|       |
   41|     42|	channel = getchannel();
   42|       |
   43|     42|	if (channel->type != &clichansess) {
  ------------------
  |  Branch (43:6): [True: 0, False: 42]
  ------------------
   44|      0|		TRACE(("leave recv_msg_channel_extended_data: chantype is wrong"))
   45|      0|		return; /* we just ignore it */
   46|      0|	}
   47|       |
   48|     42|	datatype = buf_getint(ses.payload);
   49|       |	
   50|     42|	if (datatype != SSH_EXTENDED_DATA_STDERR) {
  ------------------
  |  |   79|     42|#define SSH_EXTENDED_DATA_STDERR	1
  ------------------
  |  Branch (50:6): [True: 0, False: 42]
  ------------------
   51|      0|		TRACE(("leave recv_msg_channel_extended_data: wrong datatype: %d",
   52|      0|					datatype))
   53|      0|		return;	
   54|      0|	}
   55|       |
   56|     42|	common_recv_msg_channel_data(channel, channel->errfd, channel->extrabuf);
   57|       |
   58|     42|	TRACE(("leave recv_msg_channel_extended_data"))
   59|     42|}

cli_tty_cleanup:
  135|  2.70k|void cli_tty_cleanup() {
  136|       |
  137|  2.70k|	TRACE(("enter cli_tty_cleanup"))
  138|       |
  139|  2.70k|	if (cli_ses.tty_raw_mode == 0) {
  ------------------
  |  Branch (139:6): [True: 2.70k, False: 0]
  ------------------
  140|  2.70k|		TRACE(("leave cli_tty_cleanup: not in raw mode"))
  141|  2.70k|		return;
  142|  2.70k|	}
  143|       |
  144|      0|	if (tcsetattr(STDIN_FILENO, TCSADRAIN, &cli_ses.saved_tio) == -1) {
  ------------------
  |  Branch (144:6): [True: 0, False: 0]
  ------------------
  145|      0|		dropbear_log(LOG_WARNING, "Failed restoring TTY");
  146|      0|	} else {
  147|      0|		cli_ses.tty_raw_mode = 0; 
  148|      0|	}
  149|       |
  150|      0|	TRACE(("leave cli_tty_cleanup"))
  151|      0|}

send_msg_kexdh_init:
   72|  4.36k|void send_msg_kexdh_init() {
   73|  4.36k|	TRACE(("send_msg_kexdh_init()"))	
   74|       |
   75|  4.36k|	CHECKCLEARTOWRITE();
   76|       |
   77|  4.36k|#if DROPBEAR_FUZZ
   78|  4.36k|	if (fuzz.fuzzing && fuzz.skip_kexmaths) {
  ------------------
  |  Branch (78:6): [True: 4.36k, False: 0]
  |  Branch (78:22): [True: 4.36k, False: 0]
  ------------------
   79|  4.36k|		return;
   80|  4.36k|	}
   81|      0|#endif
   82|       |
   83|      0|	cli_kex_free_param();
   84|       |
   85|      0|	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
  ------------------
  |  |   38|      0|#define SSH_MSG_KEXDH_INIT             30
  ------------------
   86|      0|	switch (ses.newkeys->algo_kex->mode) {
  ------------------
  |  Branch (86:10): [True: 0, False: 0]
  ------------------
   87|      0|#if DROPBEAR_NORMAL_DH
   88|      0|		case DROPBEAR_KEX_NORMAL_DH:
  ------------------
  |  Branch (88:3): [True: 0, False: 0]
  ------------------
   89|      0|			cli_ses.dh_param = gen_kexdh_param();
   90|      0|			buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub);
   91|      0|			break;
   92|      0|#endif
   93|      0|#if DROPBEAR_ECDH
   94|      0|		case DROPBEAR_KEX_ECDH:
  ------------------
  |  Branch (94:3): [True: 0, False: 0]
  ------------------
   95|      0|			cli_ses.ecdh_param = gen_kexecdh_param();
   96|      0|			buf_put_ecc_raw_pubkey_string(ses.writepayload, &cli_ses.ecdh_param->key);
   97|      0|			break;
   98|      0|#endif
   99|      0|#if DROPBEAR_CURVE25519
  100|      0|		case DROPBEAR_KEX_CURVE25519:
  ------------------
  |  Branch (100:3): [True: 0, False: 0]
  ------------------
  101|      0|			cli_ses.curve25519_param = gen_kexcurve25519_param();
  102|      0|			buf_putstring(ses.writepayload, cli_ses.curve25519_param->pub, CURVE25519_LEN);
  ------------------
  |  |  122|      0|#define CURVE25519_LEN 32
  ------------------
  103|      0|			break;
  104|      0|#endif
  105|      0|#if DROPBEAR_PQHYBRID
  106|      0|		case DROPBEAR_KEX_PQHYBRID:
  ------------------
  |  Branch (106:3): [True: 0, False: 0]
  ------------------
  107|      0|			cli_ses.pqhybrid_param = gen_kexpqhybrid_param();
  108|      0|			buf_putbufstring(ses.writepayload, cli_ses.pqhybrid_param->concat_public);
  109|      0|			break;
  110|      0|#endif
  111|      0|	}
  112|       |
  113|      0|	encrypt_packet();
  114|      0|}
recv_msg_kexdh_reply:
  117|  1.78k|void recv_msg_kexdh_reply() {
  118|       |
  119|  1.78k|	sign_key *hostkey = NULL;
  120|  1.78k|	unsigned int keytype, keybloblen;
  121|  1.78k|	unsigned char* keyblob = NULL;
  122|       |
  123|  1.78k|	TRACE(("enter recv_msg_kexdh_reply"))
  124|       |	
  125|  1.78k|#if DROPBEAR_FUZZ
  126|  1.78k|	if (fuzz.fuzzing && fuzz.skip_kexmaths) {
  ------------------
  |  Branch (126:6): [True: 1.78k, False: 0]
  |  Branch (126:22): [True: 1.78k, False: 0]
  ------------------
  127|  1.78k|		return;
  128|  1.78k|	}
  129|      0|#endif
  130|       |
  131|      0|	if (cli_ses.kex_state != KEXDH_INIT_SENT) {
  ------------------
  |  Branch (131:6): [True: 0, False: 0]
  ------------------
  132|      0|		dropbear_exit("Received out-of-order kexdhreply");
  133|      0|	}
  134|      0|	keytype = ses.newkeys->algo_hostkey;
  135|      0|	TRACE(("keytype is %d", keytype))
  136|       |
  137|      0|	hostkey = new_sign_key();
  138|      0|	keybloblen = buf_getint(ses.payload);
  139|       |
  140|      0|	keyblob = buf_getptr(ses.payload, keybloblen);
  141|      0|	if (!ses.kexstate.donefirstkex) {
  ------------------
  |  Branch (141:6): [True: 0, False: 0]
  ------------------
  142|       |		/* Only makes sense the first time */
  143|      0|		checkhostkey(keyblob, keybloblen);
  144|      0|	}
  145|       |
  146|      0|	if (buf_get_pub_key(ses.payload, hostkey, &keytype) != DROPBEAR_SUCCESS) {
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  |  Branch (146:6): [True: 0, False: 0]
  ------------------
  147|      0|		TRACE(("failed getting pubkey"))
  148|      0|		dropbear_exit("Bad KEX packet");
  149|      0|	}
  150|       |
  151|       |	/* Derive the shared secret */
  152|      0|	switch (ses.newkeys->algo_kex->mode) {
  ------------------
  |  Branch (152:10): [True: 0, False: 0]
  ------------------
  153|      0|#if DROPBEAR_NORMAL_DH
  154|      0|		case DROPBEAR_KEX_NORMAL_DH:
  ------------------
  |  Branch (154:3): [True: 0, False: 0]
  ------------------
  155|      0|			{
  156|      0|			DEF_MP_INT(dh_f);
  ------------------
  |  |   81|      0|#define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
  ------------------
  157|      0|			m_mp_init(&dh_f);
  158|      0|			if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) {
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  |  Branch (158:8): [True: 0, False: 0]
  ------------------
  159|      0|				TRACE(("failed getting mpint"))
  160|      0|				dropbear_exit("Bad KEX packet");
  161|      0|			}
  162|       |
  163|      0|			kexdh_comb_key(cli_ses.dh_param, &dh_f, hostkey);
  164|      0|			mp_clear(&dh_f);
  165|      0|			}
  166|      0|			break;
  167|      0|#endif
  168|      0|#if DROPBEAR_ECDH
  169|      0|		case DROPBEAR_KEX_ECDH:
  ------------------
  |  Branch (169:3): [True: 0, False: 0]
  ------------------
  170|      0|			{
  171|      0|			buffer *ecdh_qs = buf_getstringbuf(ses.payload);
  172|      0|			kexecdh_comb_key(cli_ses.ecdh_param, ecdh_qs, hostkey);
  173|      0|			buf_free(ecdh_qs);
  174|      0|			}
  175|      0|			break;
  176|      0|#endif
  177|      0|#if DROPBEAR_CURVE25519
  178|      0|		case DROPBEAR_KEX_CURVE25519:
  ------------------
  |  Branch (178:3): [True: 0, False: 0]
  ------------------
  179|      0|			{
  180|      0|			buffer *ecdh_qs = buf_getstringbuf(ses.payload);
  181|      0|			kexcurve25519_comb_key(cli_ses.curve25519_param, ecdh_qs, hostkey);
  182|      0|			buf_free(ecdh_qs);
  183|      0|			}
  184|      0|			break;
  185|      0|#endif
  186|      0|#if DROPBEAR_PQHYBRID
  187|      0|		case DROPBEAR_KEX_PQHYBRID:
  ------------------
  |  Branch (187:3): [True: 0, False: 0]
  ------------------
  188|      0|			{
  189|      0|			buffer *q_s = buf_getstringbuf(ses.payload);
  190|      0|			kexpqhybrid_comb_key(cli_ses.pqhybrid_param, q_s, hostkey);
  191|      0|			buf_free(q_s);
  192|      0|			}
  193|      0|			break;
  194|      0|#endif
  195|      0|	}
  196|       |
  197|       |	/* Clear the local parameter */
  198|      0|	cli_kex_free_param();
  199|       |
  200|      0|	if (buf_verify(ses.payload, hostkey, ses.newkeys->algo_signature, 
  ------------------
  |  Branch (200:6): [True: 0, False: 0]
  ------------------
  201|      0|			ses.hash) != DROPBEAR_SUCCESS) {
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  202|      0|		dropbear_exit("Bad hostkey signature");
  203|      0|	}
  204|       |
  205|      0|	sign_key_free(hostkey);
  206|      0|	hostkey = NULL;
  207|       |
  208|      0|	send_msg_newkeys();
  209|      0|	ses.requirenext = SSH_MSG_NEWKEYS;
  ------------------
  |  |   37|      0|#define SSH_MSG_NEWKEYS                21
  ------------------
  210|      0|	TRACE(("leave recv_msg_kexdh_init"))
  211|      0|}
recv_msg_ext_info:
  455|  1.01k|void recv_msg_ext_info(void) {
  456|       |	/* This message is not client-specific in the protocol but Dropbear only handles
  457|       |	a server-sent message at present. */
  458|  1.01k|	unsigned int num_ext;
  459|  1.01k|	unsigned int i;
  460|       |
  461|  1.01k|	TRACE(("enter recv_msg_ext_info"))
  462|       |
  463|       |	/* Must be after the first SSH_MSG_NEWKEYS */
  464|  1.01k|	TRACE(("last %d, donefirst %d, donescond %d", ses.lastpacket, ses.kexstate.donefirstkex, ses.kexstate.donesecondkex))
  465|  1.01k|	if (!(ses.lastpacket == SSH_MSG_NEWKEYS && !ses.kexstate.donesecondkex)) {
  ------------------
  |  |   37|  2.02k|#define SSH_MSG_NEWKEYS                21
  ------------------
  |  Branch (465:8): [True: 722, False: 290]
  |  Branch (465:45): [True: 722, False: 0]
  ------------------
  466|    290|		TRACE(("leave recv_msg_ext_info: ignoring packet received at the wrong time"))
  467|    290|		return;
  468|    290|	}
  469|       |
  470|    722|	num_ext = buf_getint(ses.payload);
  471|    722|	TRACE(("received SSH_MSG_EXT_INFO with %d items", num_ext))
  472|       |
  473|  4.22k|	for (i = 0; i < num_ext; i++) {
  ------------------
  |  Branch (473:14): [True: 3.50k, False: 722]
  ------------------
  474|  3.50k|		unsigned int name_len;
  475|  3.50k|		char *ext_name = buf_getstring(ses.payload, &name_len);
  476|  3.50k|		TRACE(("extension %d name '%s'", i, ext_name))
  477|  3.50k|		if (cli_ses.server_sig_algs == NULL
  ------------------
  |  Branch (477:7): [True: 3.17k, False: 327]
  ------------------
  478|  3.17k|				&& name_len == strlen(SSH_SERVER_SIG_ALGS)
  ------------------
  |  |  101|  3.17k|#define SSH_SERVER_SIG_ALGS "server-sig-algs"
  ------------------
  |  Branch (478:8): [True: 555, False: 2.61k]
  ------------------
  479|    555|				&& strcmp(ext_name, SSH_SERVER_SIG_ALGS) == 0) {
  ------------------
  |  |  101|    555|#define SSH_SERVER_SIG_ALGS "server-sig-algs"
  ------------------
  |  Branch (479:8): [True: 102, False: 453]
  ------------------
  480|    102|			cli_ses.server_sig_algs = buf_getbuf(ses.payload);
  481|  3.39k|		} else {
  482|       |			/* valid extension values could be >MAX_STRING_LEN */
  483|  3.39k|			buf_eatstring(ses.payload);
  484|  3.39k|		}
  485|       |		m_free(ext_name);
  ------------------
  |  |   24|  3.50k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 3.50k]
  |  |  ------------------
  ------------------
  486|  3.50k|	}
  487|    722|	TRACE(("leave recv_msg_ext_info"))
  488|    722|}

cli_getopts:
  114|      1|void cli_getopts(int argc, char ** argv) {
  115|      1|	unsigned int i, j;
  116|      1|	const char ** next = NULL;
  117|      1|	enum {
  118|      1|		OPT_EXTENDED_OPTIONS,
  119|      1|#if DROPBEAR_CLI_PUBKEY_AUTH
  120|      1|		OPT_AUTHKEY,
  121|      1|#endif
  122|      1|#if DROPBEAR_CLI_LOCALTCPFWD
  123|      1|		OPT_LOCALTCPFWD,
  124|      1|#endif
  125|      1|#if DROPBEAR_CLI_REMOTETCPFWD
  126|      1|		OPT_REMOTETCPFWD,
  127|      1|#endif
  128|      1|#if DROPBEAR_CLI_NETCAT
  129|      1|		OPT_NETCAT,
  130|      1|#endif
  131|       |		/* a flag (no arg) if 'next' is NULL, a string-valued option otherwise */
  132|      1|		OPT_OTHER
  133|      1|	} opt;
  134|      1|	unsigned int cmdlen;
  135|       |
  136|      1|	const char* recv_window_arg = NULL;
  137|      1|	const char* idle_timeout_arg = NULL;
  138|      1|	const char* max_duration_arg = NULL;
  139|      1|	const char *host_arg = NULL;
  140|      1|	const char *proxycmd_arg = NULL;
  141|      1|	const char *remoteport_arg = NULL;
  142|      1|	const char *username_arg = NULL;
  143|      1|	const char *algo_print_arg = NULL;
  144|      1|	char c;
  145|       |
  146|       |	/* see printhelp() for options */
  147|      1|	cli_opts.progname = argv[0];
  148|      1|	cli_opts.remotehost = NULL;
  149|      1|	cli_opts.remotehostfixed = 0;
  150|      1|	cli_opts.remoteport = NULL;
  151|      1|	cli_opts.username = NULL;
  152|      1|	cli_opts.cmd = NULL;
  153|      1|	cli_opts.no_cmd = 0;
  154|      1|	cli_opts.quiet = 0;
  155|      1|	cli_opts.backgrounded = 0;
  156|      1|	cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
  157|      1|	cli_opts.always_accept_key = 0;
  158|      1|	cli_opts.ask_hostkey = 1;
  159|      1|	cli_opts.no_hostkey_check = 0;
  160|      1|	cli_opts.is_subsystem = 0;
  161|      1|#if DROPBEAR_CLI_PUBKEY_AUTH
  162|      1|	cli_opts.privkeys = list_new();
  163|      1|#endif
  164|      1|#if DROPBEAR_CLI_ANYTCPFWD
  165|      1|	cli_opts.exit_on_fwd_failure = 0;
  166|      1|#endif
  167|      1|	cli_opts.disable_trivial_auth = 0;
  168|      1|	cli_opts.password_authentication = 1;
  169|      1|	cli_opts.batch_mode = 0;
  170|      1|#if DROPBEAR_CLI_LOCALTCPFWD
  171|      1|	cli_opts.localfwds = list_new();
  172|      1|	opts.listen_fwd_all = 0;
  173|      1|#endif
  174|      1|#if DROPBEAR_CLI_REMOTETCPFWD
  175|      1|	cli_opts.remotefwds = list_new();
  176|      1|#endif
  177|      1|#if DROPBEAR_CLI_AGENTFWD
  178|      1|	cli_opts.agent_fwd = 0;
  179|      1|	cli_opts.agent_fd = -1;
  180|      1|	cli_opts.agent_keys_loaded = 0;
  181|      1|#endif
  182|      1|#if DROPBEAR_CLI_PROXYCMD
  183|      1|	cli_opts.proxycmd = NULL;
  184|      1|#endif
  185|      1|	cli_opts.bind_arg = NULL;
  186|      1|	cli_opts.bind_address = NULL;
  187|      1|	cli_opts.bind_port = NULL;
  188|      1|	cli_opts.keepalive_arg = NULL;
  189|       |#ifndef DISABLE_ZLIB
  190|       |	opts.compression = DROPBEAR_CLI_COMPRESSION;
  191|       |#endif
  192|      1|#if DROPBEAR_USER_ALGO_LIST
  193|      1|	opts.cipher_list = NULL;
  194|      1|	opts.mac_list = NULL;
  195|      1|#endif
  196|      1|#ifndef DISABLE_SYSLOG
  197|      1|	opts.usingsyslog = 0;
  198|      1|#endif
  199|       |	/* not yet
  200|       |	opts.ipv4 = 1;
  201|       |	opts.ipv6 = 1;
  202|       |	*/
  203|      1|	opts.recv_window = DEFAULT_RECV_WINDOW;
  ------------------
  |  |  550|      1|#define DEFAULT_RECV_WINDOW 24576
  ------------------
  204|      1|	opts.keepalive_secs = DEFAULT_KEEPALIVE;
  ------------------
  |  |  566|      1|#define DEFAULT_KEEPALIVE 0
  ------------------
  205|      1|	opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;
  ------------------
  |  |  579|      1|#define DEFAULT_IDLE_TIMEOUT 0
  ------------------
  206|      1|	opts.max_duration_secs = DEFAULT_MAX_DURATION;
  ------------------
  |  |  585|      1|#define DEFAULT_MAX_DURATION 0
  ------------------
  207|       |
  208|      1|	fill_own_user();
  209|       |
  210|      3|	for (i = 1; i < (unsigned int)argc; i++) {
  ------------------
  |  Branch (210:14): [True: 3, False: 0]
  ------------------
  211|       |		/* Handle non-flag arguments such as hostname or commands for the remote host */
  212|      3|		if (argv[i][0] != '-')
  ------------------
  |  Branch (212:7): [True: 2, False: 1]
  ------------------
  213|      2|		{
  214|      2|			if (host_arg == NULL) {
  ------------------
  |  Branch (214:8): [True: 1, False: 1]
  ------------------
  215|      1|				host_arg = argv[i];
  216|      1|				continue;
  217|      1|			}
  218|       |			/* Commands to pass to the remote host. No more flag handling,
  219|       |			commands are consumed below */
  220|      1|			break;
  221|      2|		}
  222|       |
  223|       |		/* Begins with '-' */
  224|      1|		opt = OPT_OTHER;
  225|      2|		for (j = 1; (c = argv[i][j]) != '\0' && !next && opt == OPT_OTHER; j++) {
  ------------------
  |  Branch (225:15): [True: 1, False: 1]
  |  Branch (225:43): [True: 1, False: 0]
  |  Branch (225:52): [True: 1, False: 0]
  ------------------
  226|      1|			switch (c) {
  227|      1|				case 'y':
  ------------------
  |  Branch (227:5): [True: 1, False: 0]
  ------------------
  228|       |					/* once is always accept the remote hostkey,
  229|       |					 * the same as stricthostkeychecking=accept-new */
  230|      1|					if (cli_opts.always_accept_key) {
  ------------------
  |  Branch (230:10): [True: 0, False: 1]
  ------------------
  231|       |						/* twice means no checking at all
  232|       |						 * (stricthostkeychecking=no) */
  233|      0|						cli_opts.no_hostkey_check = 1;
  234|      0|					}
  235|      1|					cli_opts.always_accept_key = 1;
  236|      1|					break;
  237|      0|				case 'q': /* quiet */
  ------------------
  |  Branch (237:5): [True: 0, False: 1]
  ------------------
  238|      0|					cli_opts.quiet = 1;
  239|      0|					break;
  240|      0|				case 'p': /* remoteport */
  ------------------
  |  Branch (240:5): [True: 0, False: 1]
  ------------------
  241|      0|					next = &remoteport_arg;
  242|      0|					break;
  243|      0|#if DROPBEAR_CLI_PUBKEY_AUTH
  244|      0|				case 'i': /* an identityfile */
  ------------------
  |  Branch (244:5): [True: 0, False: 1]
  ------------------
  245|      0|					opt = OPT_AUTHKEY;
  246|      0|					break;
  247|      0|#endif
  248|      0|				case 't': /* we want a pty */
  ------------------
  |  Branch (248:5): [True: 0, False: 1]
  ------------------
  249|      0|					cli_opts.wantpty = 1;
  250|      0|					break;
  251|      0|				case 'T': /* don't want a pty */
  ------------------
  |  Branch (251:5): [True: 0, False: 1]
  ------------------
  252|      0|					cli_opts.wantpty = 0;
  253|      0|					break;
  254|      0|				case 'N':
  ------------------
  |  Branch (254:5): [True: 0, False: 1]
  ------------------
  255|      0|					cli_opts.no_cmd = 1;
  256|      0|					break;
  257|      0|				case 'f':
  ------------------
  |  Branch (257:5): [True: 0, False: 1]
  ------------------
  258|      0|					cli_opts.backgrounded = 1;
  259|      0|					break;
  260|      0|				case 's':
  ------------------
  |  Branch (260:5): [True: 0, False: 1]
  ------------------
  261|      0|					cli_opts.is_subsystem = 1;
  262|      0|					break;
  263|      0|				case 'o':
  ------------------
  |  Branch (263:5): [True: 0, False: 1]
  ------------------
  264|      0|					opt = OPT_EXTENDED_OPTIONS;
  265|      0|					break;
  266|      0|#if DROPBEAR_CLI_LOCALTCPFWD
  267|      0|				case 'L':
  ------------------
  |  Branch (267:5): [True: 0, False: 1]
  ------------------
  268|      0|					opt = OPT_LOCALTCPFWD;
  269|      0|					break;
  270|      0|				case 'g':
  ------------------
  |  Branch (270:5): [True: 0, False: 1]
  ------------------
  271|      0|					opts.listen_fwd_all = 1;
  272|      0|					break;
  273|      0|#endif
  274|      0|#if DROPBEAR_CLI_REMOTETCPFWD
  275|      0|				case 'R':
  ------------------
  |  Branch (275:5): [True: 0, False: 1]
  ------------------
  276|      0|					opt = OPT_REMOTETCPFWD;
  277|      0|					break;
  278|      0|#endif
  279|      0|#if DROPBEAR_CLI_NETCAT
  280|      0|				case 'B':
  ------------------
  |  Branch (280:5): [True: 0, False: 1]
  ------------------
  281|      0|					opt = OPT_NETCAT;
  282|      0|					break;
  283|      0|#endif
  284|      0|#if DROPBEAR_CLI_PROXYCMD
  285|      0|				case 'J':
  ------------------
  |  Branch (285:5): [True: 0, False: 1]
  ------------------
  286|      0|					next = &proxycmd_arg;
  287|      0|					break;
  288|      0|#endif
  289|      0|				case 'l':
  ------------------
  |  Branch (289:5): [True: 0, False: 1]
  ------------------
  290|      0|					next = &username_arg;
  291|      0|					break;
  292|      0|				case 'Q':
  ------------------
  |  Branch (292:5): [True: 0, False: 1]
  ------------------
  293|      0|					next = &algo_print_arg;
  294|      0|					break;
  295|      0|				case 'h':
  ------------------
  |  Branch (295:5): [True: 0, False: 1]
  ------------------
  296|      0|					printhelp();
  297|      0|					exit(EXIT_SUCCESS);
  298|      0|					break;
  299|      0|				case 'u':
  ------------------
  |  Branch (299:5): [True: 0, False: 1]
  ------------------
  300|       |					/* backwards compatibility with old urandom option */
  301|      0|					break;
  302|      0|				case 'W':
  ------------------
  |  Branch (302:5): [True: 0, False: 1]
  ------------------
  303|      0|					next = &recv_window_arg;
  304|      0|					break;
  305|      0|				case 'K':
  ------------------
  |  Branch (305:5): [True: 0, False: 1]
  ------------------
  306|      0|					next = &cli_opts.keepalive_arg;
  307|      0|					break;
  308|      0|				case 'I':
  ------------------
  |  Branch (308:5): [True: 0, False: 1]
  ------------------
  309|      0|					next = &idle_timeout_arg;
  310|      0|					break;
  311|      0|				case 'M':
  ------------------
  |  Branch (311:5): [True: 0, False: 1]
  ------------------
  312|      0|					next = &max_duration_arg;
  313|      0|					break;
  314|      0|#if DROPBEAR_CLI_AGENTFWD
  315|      0|				case 'A':
  ------------------
  |  Branch (315:5): [True: 0, False: 1]
  ------------------
  316|      0|					cli_opts.agent_fwd = 1;
  317|      0|					break;
  318|      0|#endif
  319|      0|#if DROPBEAR_USER_ALGO_LIST
  320|      0|				case 'c':
  ------------------
  |  Branch (320:5): [True: 0, False: 1]
  ------------------
  321|      0|					next = &opts.cipher_list;
  322|      0|					break;
  323|      0|				case 'm':
  ------------------
  |  Branch (323:5): [True: 0, False: 1]
  ------------------
  324|      0|					next = &opts.mac_list;
  325|      0|					break;
  326|      0|#endif
  327|       |#if DEBUG_TRACE
  328|       |				case 'v':
  329|       |					debug_trace++;
  330|       |					break;
  331|       |#endif
  332|      0|				case 'F':
  ------------------
  |  Branch (332:5): [True: 0, False: 1]
  ------------------
  333|      0|				case 'e':
  ------------------
  |  Branch (333:5): [True: 0, False: 1]
  ------------------
  334|       |#if !DROPBEAR_USER_ALGO_LIST
  335|       |				case 'c':
  336|       |				case 'm':
  337|       |#endif
  338|      0|				case 'D':
  ------------------
  |  Branch (338:5): [True: 0, False: 1]
  ------------------
  339|       |#if !DROPBEAR_CLI_REMOTETCPFWD
  340|       |				case 'R':
  341|       |#endif
  342|       |#if !DROPBEAR_CLI_LOCALTCPFWD
  343|       |				case 'L':
  344|       |#endif
  345|      0|				case 'V':
  ------------------
  |  Branch (345:5): [True: 0, False: 1]
  ------------------
  346|      0|					print_version();
  347|      0|					exit(EXIT_SUCCESS);
  348|      0|					break;
  349|      0|				case 'b':
  ------------------
  |  Branch (349:5): [True: 0, False: 1]
  ------------------
  350|      0|					next = &cli_opts.bind_arg;
  351|      0|					break;
  352|      0|				case 'z':
  ------------------
  |  Branch (352:5): [True: 0, False: 1]
  ------------------
  353|      0|					opts.disable_ip_tos = 1;
  354|      0|					break;
  355|      0|				default:
  ------------------
  |  Branch (355:5): [True: 0, False: 1]
  ------------------
  356|      0|					fprintf(stderr,
  ------------------
  |  |  100|      0|#define stderr (fuzz.fake_stderr)
  ------------------
  357|      0|						"WARNING: Ignoring unknown option -%c\n", c);
  358|      0|					break;
  359|      1|			} /* Switch */
  360|      1|		}
  361|       |
  362|      1|		if (!next && opt == OPT_OTHER) /* got a flag */
  ------------------
  |  Branch (362:7): [True: 1, False: 0]
  |  Branch (362:16): [True: 1, False: 0]
  ------------------
  363|      1|			continue;
  364|       |
  365|      0|		if (c == '\0') {
  ------------------
  |  Branch (365:7): [True: 0, False: 0]
  ------------------
  366|      0|			i++;
  367|      0|			j = 0;
  368|      0|			if (!argv[i])
  ------------------
  |  Branch (368:8): [True: 0, False: 0]
  ------------------
  369|      0|				dropbear_exit("Missing argument");
  370|      0|		}
  371|       |
  372|      0|		if (opt == OPT_EXTENDED_OPTIONS) {
  ------------------
  |  Branch (372:7): [True: 0, False: 0]
  ------------------
  373|      0|			TRACE(("opt extended"))
  374|      0|			add_extendedopt(&argv[i][j]);
  375|      0|		}
  376|      0|		else
  377|      0|#if DROPBEAR_CLI_PUBKEY_AUTH
  378|      0|		if (opt == OPT_AUTHKEY) {
  ------------------
  |  Branch (378:7): [True: 0, False: 0]
  ------------------
  379|      0|			TRACE(("opt authkey"))
  380|      0|			loadidentityfile(&argv[i][j], 1);
  381|      0|		}
  382|      0|		else
  383|      0|#endif
  384|      0|#if DROPBEAR_CLI_REMOTETCPFWD
  385|      0|		if (opt == OPT_REMOTETCPFWD) {
  ------------------
  |  Branch (385:7): [True: 0, False: 0]
  ------------------
  386|      0|			TRACE(("opt remotetcpfwd"))
  387|      0|			addforward(&argv[i][j], cli_opts.remotefwds);
  388|      0|		}
  389|      0|		else
  390|      0|#endif
  391|      0|#if DROPBEAR_CLI_LOCALTCPFWD
  392|      0|		if (opt == OPT_LOCALTCPFWD) {
  ------------------
  |  Branch (392:7): [True: 0, False: 0]
  ------------------
  393|      0|			TRACE(("opt localtcpfwd"))
  394|      0|			addforward(&argv[i][j], cli_opts.localfwds);
  395|      0|		}
  396|      0|		else
  397|      0|#endif
  398|      0|#if DROPBEAR_CLI_NETCAT
  399|      0|		if (opt == OPT_NETCAT) {
  ------------------
  |  Branch (399:7): [True: 0, False: 0]
  ------------------
  400|      0|			TRACE(("opt netcat"))
  401|      0|			add_netcat(&argv[i][j]);
  402|      0|		}
  403|      0|		else
  404|      0|#endif
  405|      0|		if (next) {
  ------------------
  |  Branch (405:7): [True: 0, False: 0]
  ------------------
  406|       |			/* The previous flag set a value to assign */
  407|      0|			*next = &argv[i][j];
  408|      0|			if (*next == NULL)
  ------------------
  |  Branch (408:8): [True: 0, False: 0]
  ------------------
  409|      0|				dropbear_exit("Invalid null argument");
  410|      0|			next = NULL;
  411|      0|		}
  412|      0|	}
  413|       |
  414|      1|#if DROPBEAR_USER_ALGO_LIST
  415|       |	/* -c help doesn't need a hostname */
  416|      1|	parse_ciphers_macs();
  417|      1|#endif
  418|       |
  419|      1|	if (algo_print_arg) {
  ------------------
  |  Branch (419:6): [True: 0, False: 1]
  ------------------
  420|      0|		print_algos(algo_print_arg);
  421|       |		/* No return */
  422|      0|	}
  423|       |
  424|      1|	if (host_arg == NULL) { /* missing hostname */
  ------------------
  |  Branch (424:6): [True: 0, False: 1]
  ------------------
  425|      0|		printhelp();
  426|      0|		dropbear_exit("Remote host needs to provided.");
  427|      0|	}
  428|      1|	TRACE(("host is: %s", host_arg))
  429|       |
  430|      1|#if DROPBEAR_USE_SSH_CONFIG
  431|      1|	apply_config_settings(host_arg);
  432|      1|#endif
  433|       |
  434|       |	/* Apply needed defaults if missing from command line or config file. */
  435|      1|	if (remoteport_arg) {
  ------------------
  |  Branch (435:6): [True: 0, False: 1]
  ------------------
  436|      0|		m_free(cli_opts.remoteport);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  437|      0|		cli_opts.remoteport = m_strdup(remoteport_arg);
  438|      1|	} else if (!cli_opts.remoteport) {
  ------------------
  |  Branch (438:13): [True: 1, False: 0]
  ------------------
  439|      1|		cli_opts.remoteport = m_strdup("22");
  440|      1|	}
  441|       |
  442|      1|	if (username_arg) {
  ------------------
  |  Branch (442:6): [True: 0, False: 1]
  ------------------
  443|      0|		m_free(cli_opts.username);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  444|      0|		cli_opts.username = m_strdup(username_arg);
  445|      1|	} else if(!cli_opts.username) {
  ------------------
  |  Branch (445:12): [True: 1, False: 0]
  ------------------
  446|      1|		cli_opts.username = m_strdup(cli_opts.own_user);
  447|      1|	}
  448|       |
  449|       |	/* Done with options/flags; now handle the hostname (which may not
  450|       |	 * start with a hyphen) and optional command */
  451|       |
  452|      1|	if (i < (unsigned int)argc) {
  ------------------
  |  Branch (452:6): [True: 1, False: 0]
  ------------------
  453|       |		/* Build the command to send */
  454|      1|		cmdlen = 0;
  455|      2|		for (j = i; j < (unsigned int)argc; j++)
  ------------------
  |  Branch (455:15): [True: 1, False: 1]
  ------------------
  456|      1|			cmdlen += strlen(argv[j]) + 1; /* +1 for spaces */
  457|       |
  458|       |		/* Allocate the space */
  459|      1|		cli_opts.cmd = (char*)m_malloc(cmdlen);
  460|      1|		cli_opts.cmd[0] = '\0';
  461|       |
  462|       |		/* Append all the bits */
  463|      2|		for (j = i; j < (unsigned int)argc; j++) {
  ------------------
  |  Branch (463:15): [True: 1, False: 1]
  ------------------
  464|      1|			strlcat(cli_opts.cmd, argv[j], cmdlen);
  465|      1|			strlcat(cli_opts.cmd, " ", cmdlen);
  466|      1|		}
  467|       |		/* It'll be null-terminated here */
  468|      1|		TRACE(("cmd is: %s", cli_opts.cmd))
  469|      1|	}
  470|       |
  471|       |	/* And now a few sanity checks and setup */
  472|       |
  473|      1|#if DROPBEAR_CLI_PROXYCMD
  474|      1|	if (proxycmd_arg) {
  ------------------
  |  Branch (474:6): [True: 0, False: 1]
  ------------------
  475|       |		/* To match the common path of m_freeing it */
  476|      0|		cli_opts.proxycmd = m_strdup(proxycmd_arg);
  477|      0|	}
  478|      1|#endif
  479|       |
  480|      1|	if (cli_opts.bind_arg) {
  ------------------
  |  Branch (480:6): [True: 0, False: 1]
  ------------------
  481|      0|		if (split_address_port(cli_opts.bind_arg,
  ------------------
  |  Branch (481:7): [True: 0, False: 0]
  ------------------
  482|      0|			&cli_opts.bind_address, &cli_opts.bind_port)
  483|      0|				== DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  484|      0|			dropbear_exit("Bad -b argument");
  485|      0|		}
  486|      0|	}
  487|       |
  488|       |	/* If not explicitly specified with -t or -T, we don't want a pty if
  489|       |	 * there's a command, but we do otherwise */
  490|      1|	if (cli_opts.wantpty == 9) {
  ------------------
  |  Branch (490:6): [True: 1, False: 0]
  ------------------
  491|      1|		if (cli_opts.cmd == NULL) {
  ------------------
  |  Branch (491:7): [True: 0, False: 1]
  ------------------
  492|      0|			if (isatty(STDIN_FILENO)) {
  ------------------
  |  Branch (492:8): [True: 0, False: 0]
  ------------------
  493|      0|				cli_opts.wantpty = 1;
  494|      0|			} else {
  495|      0|				TRACE(("Not a TTY"));
  496|      0|				cli_opts.wantpty = 0;
  497|      0|			}
  498|      1|		} else {
  499|      1|			cli_opts.wantpty = 0;
  500|      1|		}
  501|      1|	}
  502|       |
  503|      1|	if (cli_opts.backgrounded && cli_opts.cmd == NULL
  ------------------
  |  Branch (503:6): [True: 0, False: 1]
  |  Branch (503:31): [True: 0, False: 0]
  ------------------
  504|      0|			&& cli_opts.no_cmd == 0) {
  ------------------
  |  Branch (504:7): [True: 0, False: 0]
  ------------------
  505|      0|		dropbear_exit("Command required for -f");
  506|      0|	}
  507|       |
  508|      1|	if (recv_window_arg) {
  ------------------
  |  Branch (508:6): [True: 0, False: 1]
  ------------------
  509|      0|		parse_recv_window(recv_window_arg);
  510|      0|	}
  511|      1|	if (cli_opts.keepalive_arg) {
  ------------------
  |  Branch (511:6): [True: 0, False: 1]
  ------------------
  512|      0|		unsigned int val;
  513|      0|		if (m_str_to_uint(cli_opts.keepalive_arg, &val) == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (513:7): [True: 0, False: 0]
  ------------------
  514|      0|			dropbear_exit("Bad keepalive '%s'", cli_opts.keepalive_arg);
  515|      0|		}
  516|      0|		opts.keepalive_secs = val;
  517|      0|	}
  518|       |
  519|      1|	if (idle_timeout_arg) {
  ------------------
  |  Branch (519:6): [True: 0, False: 1]
  ------------------
  520|      0|		unsigned int val;
  521|      0|		if (m_str_to_uint(idle_timeout_arg, &val) == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (521:7): [True: 0, False: 0]
  ------------------
  522|      0|			dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
  523|      0|		}
  524|      0|		opts.idle_timeout_secs = val;
  525|      0|	}
  526|       |
  527|      1|	if (max_duration_arg) {
  ------------------
  |  Branch (527:6): [True: 0, False: 1]
  ------------------
  528|      0|		unsigned int val;
  529|      0|		if (m_str_to_uint(max_duration_arg, &val) == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (529:7): [True: 0, False: 0]
  ------------------
  530|      0|			dropbear_exit("Bad max_duration '%s'", max_duration_arg);
  531|      0|		}
  532|      0|		opts.max_duration_secs = val;
  533|      0|	}
  534|       |
  535|      1|#if DROPBEAR_CLI_NETCAT
  536|      1|	if (cli_opts.cmd && cli_opts.netcat_host) {
  ------------------
  |  Branch (536:6): [True: 1, False: 0]
  |  Branch (536:22): [True: 0, False: 1]
  ------------------
  537|      0|		dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
  538|      0|	}
  539|      1|#endif
  540|       |
  541|       |	/* The hostname gets set up last, since
  542|       |	 * in multi-hop mode it will require knowledge
  543|       |	 * of other flags such as -i */
  544|      1|#if DROPBEAR_CLI_MULTIHOP
  545|      1|	parse_multihop_hostname(host_arg, argv[0]);
  546|       |#else
  547|       |	parse_hostname(host_arg);
  548|       |#endif
  549|       |
  550|       |	/* We don't want to include default id_dropbear as a
  551|       |	   -i argument for multihop, so handle it later. */
  552|      1|#if (DROPBEAR_CLI_PUBKEY_AUTH)
  553|      1|	{
  554|      1|		loadidentityfile(DROPBEAR_DEFAULT_CLI_AUTHKEY, 0);
  ------------------
  |  |  408|      1|#define DROPBEAR_DEFAULT_CLI_AUTHKEY "~/.ssh/id_dropbear"
  ------------------
  555|      1|	}
  556|      1|#endif
  557|      1|}
loadidentityfile:
  560|      1|void loadidentityfile(const char* filename, int warnfail) {
  561|      1|	sign_key *key;
  562|      1|	enum signkey_type keytype;
  563|       |
  564|      1|	char *id_key_path = expand_homedir_path(filename);
  565|      1|	TRACE(("loadidentityfile %s", id_key_path))
  566|       |
  567|      1|	key = new_sign_key();
  568|      1|	keytype = DROPBEAR_SIGNKEY_ANY;
  569|      1|	if ( readhostkey(id_key_path, key, &keytype) != DROPBEAR_SUCCESS ) {
  ------------------
  |  |  111|      1|#define DROPBEAR_SUCCESS 0
  ------------------
  |  Branch (569:7): [True: 1, False: 0]
  ------------------
  570|      1|		if (warnfail) {
  ------------------
  |  Branch (570:7): [True: 0, False: 1]
  ------------------
  571|      0|			dropbear_log(LOG_WARNING, "Failed loading keyfile '%s'\n", id_key_path);
  572|      0|		}
  573|      1|		sign_key_free(key);
  574|      1|		m_free(id_key_path);
  ------------------
  |  |   24|      1|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1]
  |  |  ------------------
  ------------------
  575|      1|	} else {
  576|      0|		key->type = keytype;
  577|      0|		key->source = SIGNKEY_SOURCE_RAW_FILE;
  578|      0|		key->filename = id_key_path;
  579|      0|		list_append(cli_opts.privkeys, key);
  580|      0|	}
  581|      1|}
cli-runopts.c:parse_multihop_hostname:
  697|      1|static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
  698|      1|	char *userhostarg = NULL;
  699|      1|	char *hostbuf = NULL;
  700|      1|	char *last_hop = NULL;
  701|      1|	char *prior_hops = NULL;
  702|       |
  703|       |	/* both scp and rsync parse a user@host argument
  704|       |	 * and turn it into "-l user host". This breaks
  705|       |	 * for our multihop syntax, so we suture it back together.
  706|       |	 * This will break usernames that have both '@' and ',' in them,
  707|       |	 * though that should be fairly uncommon. */
  708|      1|	if (cli_opts.username
  ------------------
  |  Branch (708:6): [True: 1, False: 0]
  ------------------
  709|      1|			&& strchr(cli_opts.username, ',')
  ------------------
  |  Branch (709:7): [True: 0, False: 1]
  ------------------
  710|      0|			&& strchr(cli_opts.username, '@')) {
  ------------------
  |  Branch (710:7): [True: 0, False: 0]
  ------------------
  711|      0|		unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
  712|      0|		hostbuf = m_malloc(len);
  713|      0|		m_snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
  714|      1|	} else {
  715|      1|		hostbuf = m_strdup(orighostarg);
  716|      1|	}
  717|      1|	userhostarg = hostbuf;
  718|       |
  719|       |	/* Split off any last hostname and use that as remotehost/remoteport.
  720|       |	 * That is used for authorized_keys checking etc */
  721|      1|	last_hop = strrchr(userhostarg, ',');
  722|      1|	if (last_hop) {
  ------------------
  |  Branch (722:6): [True: 0, False: 1]
  ------------------
  723|      0|		if (last_hop == userhostarg) {
  ------------------
  |  Branch (723:7): [True: 0, False: 0]
  ------------------
  724|      0|			dropbear_exit("Bad multi-hop hostnames");
  725|      0|		}
  726|      0|		*last_hop = '\0';
  727|      0|		last_hop++;
  728|      0|		prior_hops = userhostarg;
  729|      0|		userhostarg = last_hop;
  730|      0|	}
  731|       |
  732|       |	/* Update cli_opts.remotehost and cli_opts.remoteport */
  733|      1|	parse_hostname(userhostarg);
  734|       |
  735|       |	/* Construct any multihop proxy command. Use proxyexec to
  736|       |	 * avoid worrying about shell escaping. */
  737|      1|	if (prior_hops) {
  ------------------
  |  Branch (737:6): [True: 0, False: 1]
  ------------------
  738|      0|		cli_opts.proxyexec = multihop_args(argv0, prior_hops);
  739|       |		/* Any -J argument has been copied to proxyexec */
  740|      0|		if (cli_opts.proxycmd) {
  ------------------
  |  Branch (740:7): [True: 0, False: 0]
  ------------------
  741|      0|			m_free(cli_opts.proxycmd);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  742|      0|		}
  743|       |
  744|       |#ifndef DISABLE_ZLIB
  745|       |		/* This outer stream will be incompressible since it's encrypted. */
  746|       |		opts.compression = 0;
  747|       |#endif
  748|      0|	}
  749|       |
  750|       |	m_free(hostbuf);
  ------------------
  |  |   24|      1|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1]
  |  |  ------------------
  ------------------
  751|      1|}
cli-runopts.c:parse_hostname:
  755|      1|static void parse_hostname(const char* orighostarg) {
  756|      1|	char *userhostarg = NULL;
  757|      1|	char *port = NULL;
  758|      1|	char* remotehost = NULL;
  759|       |
  760|      1|	userhostarg = m_strdup(orighostarg);
  761|       |
  762|      1|	remotehost = strchr(userhostarg, '@');
  763|      1|	if (remotehost == NULL) {
  ------------------
  |  Branch (763:6): [True: 1, False: 0]
  ------------------
  764|       |		/* no username portion, the cli-auth.c code can figure the
  765|       |		 * local user's name */
  766|      1|		remotehost = userhostarg;
  767|      1|	} else {
  768|      0|		remotehost[0] = '\0'; /* Split the user/host */
  769|      0|		remotehost++;
  770|      0|		cli_opts.username = m_strdup(userhostarg);
  771|      0|	}
  772|       |
  773|      1|	port = strchr(remotehost, '^');
  774|      1|	if (!port)  {
  ------------------
  |  Branch (774:6): [True: 1, False: 0]
  ------------------
  775|       |		/* legacy separator */
  776|      1|		port = strchr(remotehost, '/');
  777|      1|	}
  778|      1|	if (port) {
  ------------------
  |  Branch (778:6): [True: 0, False: 1]
  ------------------
  779|      0|		*port = '\0';
  780|      0|		cli_opts.remoteport = m_strdup(port+1);
  781|      0|	}
  782|       |
  783|      1|	if (remotehost[0] == '\0') {
  ------------------
  |  Branch (783:6): [True: 0, False: 1]
  ------------------
  784|      0|		dropbear_exit("Bad hostname.");
  785|      0|	}
  786|       |
  787|      1|	if (!cli_opts.remotehostfixed) {
  ------------------
  |  Branch (787:6): [True: 1, False: 0]
  ------------------
  788|      1|		cli_opts.remotehost = m_strdup(remotehost);
  789|      1|	}
  790|       |	m_free(userhostarg);
  ------------------
  |  |   24|      1|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1]
  |  |  ------------------
  ------------------
  791|      1|}
cli-runopts.c:fill_own_user:
  830|      1|static void fill_own_user() {
  831|      1|	uid_t uid;
  832|      1|	struct passwd *pw = NULL;
  833|       |
  834|      1|	uid = getuid();
  835|       |
  836|      1|	pw = getpwuid(uid);
  ------------------
  |  |  109|      1|#define getpwuid(x) fuzz_getpwuid(x)
  ------------------
  837|      1|	if (pw && pw->pw_name != NULL) {
  ------------------
  |  Branch (837:6): [True: 1, False: 0]
  |  Branch (837:12): [True: 1, False: 0]
  ------------------
  838|      1|		cli_opts.own_user = m_strdup(pw->pw_name);
  839|      1|	} else {
  840|      0|		dropbear_log(LOG_INFO, "Warning: failed to identify current user. Trying anyway.");
  841|      0|		cli_opts.own_user = m_strdup("unknown");
  842|      0|	}
  843|       |
  844|      1|}
cli-runopts.c:apply_config_settings:
 1140|      1|static void apply_config_settings(const char* cli_host_arg) {
 1141|      1|	char* is_multi_hop_host_target = strchr(cli_host_arg, ',');
 1142|      1|	if (!is_multi_hop_host_target) {
  ------------------
  |  Branch (1142:6): [True: 1, False: 0]
  ------------------
 1143|      1|		char* config_path = expand_homedir_path(DROPBEAR_DEFAULT_SSH_CONFIG);
  ------------------
  |  |  118|      1|#define DROPBEAR_DEFAULT_SSH_CONFIG "~/.ssh/dropbear_config"
  ------------------
 1144|      1|		FILE* f;
 1145|      1|		if ((f = fopen(config_path, "r")) == NULL) {
  ------------------
  |  Branch (1145:7): [True: 1, False: 0]
  ------------------
 1146|      1|			DEBUG1(("Configuration file '%.200s' not found.", config_path));
 1147|      1|		}
 1148|      0|		else {
 1149|      0|			parse_hostname(cli_host_arg); /* Needed as key into the config. */
 1150|      0|			read_config_file(config_path, f, &cli_opts);
 1151|      0|			fclose(f);
 1152|      0|		}
 1153|       |		m_free(config_path);
  ------------------
  |  |   24|      1|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1]
  |  |  ------------------
  ------------------
 1154|      1|	}
 1155|      1|}

cli_session:
  112|  2.70k|void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress, pid_t proxy_cmd_pid) {
  113|       |
  114|  2.70k|	common_session_init(sock_in, sock_out);
  115|       |
  116|  2.70k|	if (progress) {
  ------------------
  |  Branch (116:6): [True: 0, False: 2.70k]
  ------------------
  117|      0|		connect_set_writequeue(progress, &ses.writequeue);
  118|      0|	}
  119|       |
  120|  2.70k|	chaninitialise(cli_chantypes);
  121|  2.70k|	cli_algos_initialise();
  122|       |
  123|       |	/* Set up cli_ses vars */
  124|  2.70k|	cli_session_init(proxy_cmd_pid);
  125|       |
  126|       |	/* Ready to go */
  127|  2.70k|	ses.init_done = 1;
  128|       |
  129|       |	/* Exchange identification */
  130|  2.70k|	send_session_identification();
  131|       |
  132|  2.70k|	kexfirstinitialise(); /* initialise the kex state */
  133|       |
  134|  2.70k|	send_msg_kexinit();
  135|       |
  136|  2.70k|	session_loop(cli_sessionloop);
  137|       |
  138|       |	/* Not reached */
  139|       |
  140|  2.70k|}
kill_proxy_command:
  338|  2.70k|void kill_proxy_command(void) {
  339|       |	/*
  340|       |	 * Send SIGHUP to proxy command if used. We don't wait() in
  341|       |	 * case it hangs and instead rely on init to reap the child
  342|       |	 */
  343|  2.70k|	if (cli_ses.proxy_cmd_pid > 1) {
  ------------------
  |  Branch (343:6): [True: 0, False: 2.70k]
  ------------------
  344|      0|		TRACE(("killing proxy command with PID='%d'", cli_ses.proxy_cmd_pid));
  345|      0|		kill(cli_ses.proxy_cmd_pid, SIGHUP);
  ------------------
  |  |   57|      0|#define kill(pid, sig) fuzz_kill(pid, sig)
  ------------------
  346|      0|	}
  347|  2.70k|}
cleantext:
  400|  1.11k|void cleantext(char* dirtytext) {
  401|       |
  402|  1.11k|	unsigned int i, j;
  403|  1.11k|	char c;
  404|       |
  405|  1.11k|	j = 0;
  406|  21.6k|	for (i = 0; dirtytext[i] != '\0'; i++) {
  ------------------
  |  Branch (406:14): [True: 20.5k, False: 1.11k]
  ------------------
  407|       |
  408|  20.5k|		c = dirtytext[i];
  409|       |		/* We can ignore '\r's */
  410|  20.5k|		if ( (c >= ' ' && c <= '~') || c == '\n' || c == '\t') {
  ------------------
  |  Branch (410:9): [True: 1.84k, False: 18.6k]
  |  Branch (410:21): [True: 1.24k, False: 595]
  |  Branch (410:34): [True: 14.6k, False: 4.59k]
  |  Branch (410:47): [True: 208, False: 4.38k]
  ------------------
  411|  16.1k|			dirtytext[j] = c;
  412|  16.1k|			j++;
  413|  16.1k|		}
  414|  20.5k|	}
  415|       |	/* Null terminate */
  416|  1.11k|	dirtytext[j] = '\0';
  417|  1.11k|}
cli_dropbear_exit:
  433|  2.70k|void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
  434|  2.70k|	char exitmsg[400];
  435|  2.70k|	char fullmsg[550];
  436|       |
  437|       |	/* Note that exit message must be rendered before session cleanup */
  438|       |
  439|       |	/* Render the formatted exit message */
  440|  2.70k|	vsnprintf(exitmsg, sizeof(exitmsg), format, param);
  441|  2.70k|	TRACE(("Exited, cleaning up: %s", exitmsg))
  442|       |
  443|       |	/* Add the prefix depending on session/auth state */
  444|  2.70k|	if (!ses.init_done) {
  ------------------
  |  Branch (444:6): [True: 0, False: 2.70k]
  ------------------
  445|      0|		snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
  446|  2.70k|	} else {
  447|  2.70k|		snprintf(fullmsg, sizeof(fullmsg), 
  448|  2.70k|				"Connection to %s@%s:%s exited: %s", 
  449|  2.70k|				cli_opts.username, cli_opts.remotehost, 
  450|  2.70k|				cli_opts.remoteport, exitmsg);
  451|  2.70k|	}
  452|       |
  453|       |	/* Do the cleanup first, since then the terminal will be reset */
  454|  2.70k|	session_cleanup();
  455|       |	
  456|  2.70k|#if DROPBEAR_FUZZ
  457|  2.70k|    if (fuzz.do_jmp) {
  ------------------
  |  Branch (457:9): [True: 2.70k, False: 0]
  ------------------
  458|  2.70k|        longjmp(fuzz.jmp, 1);
  459|  2.70k|    }
  460|      0|#endif
  461|       |
  462|       |	/* Avoid printing onwards from terminal cruft */
  463|      0|	fprintf(stderr, "\n");
  ------------------
  |  |  100|      0|#define stderr (fuzz.fake_stderr)
  ------------------
  464|       |
  465|      0|	dropbear_log(LOG_INFO, "%s", fullmsg);
  466|       |
  467|      0|	exit(exitcode);
  468|  2.70k|}
cli_dropbear_log:
  470|    697|void cli_dropbear_log(int priority, const char* format, va_list param) {
  471|       |
  472|    697|	char printbuf[1024];
  473|    697|	const char *name;
  474|       |
  475|    697|	name = cli_opts.progname;
  476|    697|	if (!name) {
  ------------------
  |  Branch (476:6): [True: 0, False: 697]
  ------------------
  477|      0|		name = "dbclient";
  478|      0|	}
  479|       |
  480|    697|	vsnprintf(printbuf, sizeof(printbuf), format, param);
  481|       |
  482|    697|#ifndef DISABLE_SYSLOG
  483|    697|	if (opts.usingsyslog) {
  ------------------
  |  Branch (483:6): [True: 0, False: 697]
  ------------------
  484|      0|		syslog(priority, "%s", printbuf);
  485|      0|	}
  486|    697|#endif
  487|       |
  488|    697|	fprintf(stderr, "%s: %s\n", name, printbuf);
  ------------------
  |  |  100|    697|#define stderr (fuzz.fake_stderr)
  ------------------
  489|    697|	fflush(stderr);
  ------------------
  |  |  100|    697|#define stderr (fuzz.fake_stderr)
  ------------------
  490|    697|}
cli-session.c:cli_session_init:
  148|  2.70k|static void cli_session_init(pid_t proxy_cmd_pid) {
  149|       |
  150|  2.70k|	cli_ses.state = STATE_NOTHING;
  151|  2.70k|	cli_ses.kex_state = KEX_NOTHING;
  152|       |
  153|  2.70k|	cli_ses.tty_raw_mode = 0;
  154|  2.70k|	cli_ses.winchange = 0;
  155|       |
  156|       |	/* We store std{in,out,err}'s flags, so we can set them back on exit
  157|       |	 * (otherwise busybox's ash isn't happy */
  158|  2.70k|	cli_ses.stdincopy = dup(STDIN_FILENO);
  159|  2.70k|	cli_ses.stdinflags = fcntl(STDIN_FILENO, F_GETFL, 0);
  160|  2.70k|	cli_ses.stdoutcopy = dup(STDOUT_FILENO);
  161|  2.70k|	cli_ses.stdoutflags = fcntl(STDOUT_FILENO, F_GETFL, 0);
  162|  2.70k|	cli_ses.stderrcopy = dup(STDERR_FILENO);
  163|  2.70k|	cli_ses.stderrflags = fcntl(STDERR_FILENO, F_GETFL, 0);
  164|       |
  165|  2.70k|	cli_ses.retval = EXIT_SUCCESS; /* Assume it's clean if we don't get a
  166|       |									  specific exit status */
  167|  2.70k|	cli_ses.proxy_cmd_pid = proxy_cmd_pid;
  168|  2.70k|	TRACE(("proxy command PID='%d'", proxy_cmd_pid));
  169|       |
  170|       |	/* Auth */
  171|  2.70k|	cli_ses.lastprivkey = NULL;
  172|  2.70k|	cli_ses.lastauthtype = 0;
  173|  2.70k|	cli_ses.is_trivial_auth = 1;
  174|       |
  175|       |	/* For printing "remote host closed" for the user */
  176|  2.70k|	ses.remoteclosed = cli_remoteclosed;
  177|       |
  178|  2.70k|	ses.extra_session_cleanup = cli_session_cleanup;
  179|       |
  180|       |	/* packet handlers */
  181|  2.70k|	ses.packettypes = cli_packettypes;
  182|       |
  183|  2.70k|	ses.isserver = 0;
  184|       |
  185|  2.70k|#if DROPBEAR_KEX_FIRST_FOLLOWS
  186|  2.70k|	ses.send_kex_first_guess = cli_send_kex_first_guess;
  187|  2.70k|#endif
  188|       |
  189|  2.70k|}
cli-session.c:cli_remoteclosed:
  386|  1.37k|static void cli_remoteclosed() {
  387|       |
  388|       |	/* XXX TODO perhaps print a friendlier message if we get this but have
  389|       |	 * already sent/received disconnect message(s) ??? */
  390|  1.37k|	m_close(ses.sock_in);
  391|  1.37k|	m_close(ses.sock_out);
  392|  1.37k|	ses.sock_in = -1;
  393|  1.37k|	ses.sock_out = -1;
  394|  1.37k|	dropbear_exit("Remote closed the connection");
  395|  1.37k|}
cli-session.c:cli_session_cleanup:
  349|  2.70k|static void cli_session_cleanup(void) {
  350|       |
  351|  2.70k|	if (!ses.init_done) {
  ------------------
  |  Branch (351:6): [True: 0, False: 2.70k]
  ------------------
  352|      0|		return;
  353|      0|	}
  354|       |
  355|  2.70k|	kill_proxy_command();
  356|       |
  357|       |	/* Set std{in,out,err} back to non-blocking - busybox ash dies nastily if
  358|       |	 * we don't revert the flags */
  359|       |	/* Ignore return value since there's nothing we can do */
  360|  2.70k|	(void)fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
  361|  2.70k|	(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
  362|  2.70k|	(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
  363|       |
  364|       |	/* Don't leak */
  365|  2.70k|	m_close(cli_ses.stdincopy);
  366|  2.70k|	m_close(cli_ses.stdoutcopy);
  367|  2.70k|	m_close(cli_ses.stderrcopy);
  368|       |
  369|  2.70k|	cli_tty_cleanup();
  370|  2.70k|	if (cli_ses.server_sig_algs) {
  ------------------
  |  Branch (370:6): [True: 27, False: 2.67k]
  ------------------
  371|     27|		buf_free(cli_ses.server_sig_algs);
  372|     27|	}
  373|  2.70k|}
cli-session.c:recv_msg_service_accept:
  204|    216|static void recv_msg_service_accept(void) {
  205|       |	/* do nothing, if it failed then the server MUST have disconnected */
  206|    216|}
cli-session.c:recv_msg_global_request_cli:
  419|    918|static void recv_msg_global_request_cli(void) {
  420|    918|	unsigned int wantreply = 0;
  421|       |
  422|    918|	buf_eatstring(ses.payload);
  423|    918|	wantreply = buf_getbool(ses.payload);
  424|       |
  425|    918|	TRACE(("recv_msg_global_request_cli: want_reply: %u", wantreply));
  426|       |
  427|    918|	if (wantreply) {
  ------------------
  |  Branch (427:6): [True: 670, False: 248]
  ------------------
  428|       |		/* Send a proper rejection */
  429|    670|		send_msg_request_failure();
  430|    670|	}
  431|    918|}
cli-session.c:cli_send_kex_first_guess:
  143|  2.70k|static void cli_send_kex_first_guess() {
  144|  2.70k|	send_msg_kexdh_init();
  145|  2.70k|}
cli-session.c:cli_sessionloop:
  210|   136k|static void cli_sessionloop() {
  211|       |
  212|   136k|	TRACE2(("enter cli_sessionloop"))
  213|       |
  214|   136k|	if (ses.lastpacket == 0) {
  ------------------
  |  Branch (214:6): [True: 21.5k, False: 114k]
  ------------------
  215|  21.5k|		TRACE2(("exit cli_sessionloop: no real packets yet"))
  216|  21.5k|		return;
  217|  21.5k|	}
  218|       |
  219|   114k|	if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
  ------------------
  |  |   36|   229k|#define SSH_MSG_KEXINIT                20
  ------------------
  |  Branch (219:6): [True: 7.50k, False: 107k]
  |  Branch (219:43): [True: 1.65k, False: 5.84k]
  ------------------
  220|       |		/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
  221|       |		 * negotiation would have failed. */
  222|  1.65k|		if (!ses.kexstate.our_first_follows_matches) {
  ------------------
  |  Branch (222:7): [True: 1.65k, False: 1]
  ------------------
  223|  1.65k|			send_msg_kexdh_init();
  224|  1.65k|		}
  225|  1.65k|		cli_ses.kex_state = KEXDH_INIT_SENT;			
  226|  1.65k|		TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"))
  227|  1.65k|		return;
  228|  1.65k|	}
  229|       |
  230|       |	/* A KEX has finished, so we should go back to our KEX_NOTHING state */
  231|   113k|	if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.sentnewkeys) {
  ------------------
  |  Branch (231:6): [True: 51.1k, False: 61.8k]
  |  Branch (231:42): [True: 0, False: 51.1k]
  ------------------
  232|      0|		cli_ses.kex_state = KEX_NOTHING;
  233|      0|	}
  234|       |
  235|       |	/* We shouldn't do anything else if a KEX is in progress */
  236|   113k|	if (cli_ses.kex_state != KEX_NOTHING) {
  ------------------
  |  Branch (236:6): [True: 51.1k, False: 61.8k]
  ------------------
  237|  51.1k|		TRACE(("leave cli_sessionloop: kex_state != KEX_NOTHING"))
  238|  51.1k|		return;
  239|  51.1k|	}
  240|       |
  241|  61.8k|	if (ses.kexstate.donefirstkex == 0) {
  ------------------
  |  Branch (241:6): [True: 0, False: 61.8k]
  ------------------
  242|       |		/* We might reach here if we have partial packet reads or have
  243|       |		 * received SSG_MSG_IGNORE etc. Just skip it */
  244|      0|		TRACE2(("donefirstkex false\n"))
  245|      0|		return;
  246|      0|	}
  247|       |
  248|  61.8k|	switch (cli_ses.state) {
  249|       |
  250|    591|		case STATE_NOTHING:
  ------------------
  |  Branch (250:3): [True: 591, False: 61.2k]
  ------------------
  251|       |			/* We've got the transport layer sorted, we now need to request
  252|       |			 * userauth */
  253|    591|			send_msg_service_request(SSH_SERVICE_USERAUTH);
  ------------------
  |  |  108|    591|#define SSH_SERVICE_USERAUTH "ssh-userauth"
  ------------------
  254|       |			/* We aren't using any "implicit server authentication" methods,
  255|       |			so don't need to wait for a response for SSH_SERVICE_USERAUTH
  256|       |			before sending the auth messages (rfc4253 10) */
  257|    591|			cli_auth_getmethods();
  258|    591|			cli_ses.state = USERAUTH_REQ_SENT;
  259|    591|			TRACE(("leave cli_sessionloop: sent userauth methods req"))
  260|    591|			return;
  261|       |
  262|  61.2k|		case USERAUTH_REQ_SENT:
  ------------------
  |  Branch (262:3): [True: 61.2k, False: 591]
  ------------------
  263|  61.2k|			TRACE(("leave cli_sessionloop: waiting, req_sent"))
  264|  61.2k|			return;
  265|       |			
  266|      0|		case USERAUTH_FAIL_RCVD:
  ------------------
  |  Branch (266:3): [True: 0, False: 61.8k]
  ------------------
  267|      0|			if (cli_auth_try() == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (267:8): [True: 0, False: 0]
  ------------------
  268|      0|				dropbear_exit("No auth methods could be used.");
  269|      0|			}
  270|      0|			cli_ses.state = USERAUTH_REQ_SENT;
  271|      0|			TRACE(("leave cli_sessionloop: cli_auth_try"))
  272|      0|			return;
  273|       |
  274|      0|		case USERAUTH_SUCCESS_RCVD:
  ------------------
  |  Branch (274:3): [True: 0, False: 61.8k]
  ------------------
  275|      0|#ifndef DISABLE_SYSLOG
  276|      0|			if (opts.usingsyslog) {
  ------------------
  |  Branch (276:8): [True: 0, False: 0]
  ------------------
  277|      0|				dropbear_log(LOG_INFO, "Authentication succeeded.");
  278|      0|			}
  279|      0|#endif
  280|       |
  281|      0|			if (cli_opts.backgrounded) {
  ------------------
  |  Branch (281:8): [True: 0, False: 0]
  ------------------
  282|      0|				int devnull;
  283|       |				/* keeping stdin open steals input from the terminal and
  284|       |				   is confusing, though stdout/stderr could be useful. */
  285|      0|				devnull = open(DROPBEAR_PATH_DEVNULL, O_RDONLY);
  ------------------
  |  |   53|      0|#define DROPBEAR_PATH_DEVNULL "/dev/null"
  ------------------
  286|      0|				if (devnull < 0) {
  ------------------
  |  Branch (286:9): [True: 0, False: 0]
  ------------------
  287|      0|					dropbear_exit("Opening /dev/null: %d %s",
  288|      0|							errno, strerror(errno));
  289|      0|				}
  290|      0|				dup2(devnull, STDIN_FILENO);
  291|      0|				if (daemon(0, 1) < 0) {
  ------------------
  |  Branch (291:9): [True: 0, False: 0]
  ------------------
  292|      0|					dropbear_exit("Backgrounding failed: %d %s", 
  293|      0|							errno, strerror(errno));
  294|      0|				}
  295|      0|			}
  296|       |			
  297|      0|#if DROPBEAR_CLI_NETCAT
  298|      0|			if (cli_opts.netcat_host) {
  ------------------
  |  Branch (298:8): [True: 0, False: 0]
  ------------------
  299|      0|				cli_send_netcat_request();
  300|      0|			} else 
  301|      0|#endif
  302|      0|			if (!cli_opts.no_cmd) {
  ------------------
  |  Branch (302:8): [True: 0, False: 0]
  ------------------
  303|      0|				cli_send_chansess_request();
  304|      0|			}
  305|       |
  306|      0|#if DROPBEAR_CLI_LOCALTCPFWD
  307|      0|			setup_localtcp();
  308|      0|#endif
  309|      0|#if DROPBEAR_CLI_REMOTETCPFWD
  310|      0|			setup_remotetcp();
  311|      0|#endif
  312|       |
  313|      0|			TRACE(("leave cli_sessionloop: running"))
  314|      0|			cli_ses.state = SESSION_RUNNING;
  315|      0|			return;
  316|       |
  317|      0|		case SESSION_RUNNING:
  ------------------
  |  Branch (317:3): [True: 0, False: 61.8k]
  ------------------
  318|      0|			if (ses.chancount < 1 && !cli_opts.no_cmd) {
  ------------------
  |  Branch (318:8): [True: 0, False: 0]
  |  Branch (318:29): [True: 0, False: 0]
  ------------------
  319|      0|				cli_finished();
  320|      0|			}
  321|       |
  322|      0|			if (cli_ses.winchange) {
  ------------------
  |  Branch (322:8): [True: 0, False: 0]
  ------------------
  323|      0|				cli_chansess_winchange();
  324|      0|			}
  325|      0|			return;
  326|       |
  327|       |		/* XXX more here needed */
  328|       |
  329|       |
  330|      0|	default:
  ------------------
  |  Branch (330:2): [True: 0, False: 61.8k]
  ------------------
  331|      0|		break;
  332|  61.8k|	}
  333|       |
  334|  61.8k|	TRACE2(("leave cli_sessionloop: fell out"))
  335|       |
  336|  61.8k|}
cli-session.c:send_msg_service_request:
  191|    591|static void send_msg_service_request(const char* servicename) {
  192|       |
  193|    591|	TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
  194|       |
  195|    591|	CHECKCLEARTOWRITE();
  196|       |
  197|    591|	buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
  ------------------
  |  |   33|    591|#define SSH_MSG_SERVICE_REQUEST        5
  ------------------
  198|    591|	buf_putstring(ses.writepayload, servicename, strlen(servicename));
  199|       |
  200|    591|	encrypt_packet();
  201|    591|	TRACE(("leave send_msg_service_request"))
  202|    591|}
cli-session.c:cli_algos_initialise:
  492|  2.70k|static void cli_algos_initialise(void) {
  493|  2.70k|	algo_type *algo;
  494|  37.8k|	for (algo = sshkex; algo->name; algo++) {
  ------------------
  |  Branch (494:22): [True: 35.1k, False: 2.70k]
  ------------------
  495|  35.1k|		if (strcmp(algo->name, SSH_STRICT_KEX_S) == 0) {
  ------------------
  |  |  104|  35.1k|#define SSH_STRICT_KEX_S "kex-strict-s-v00@openssh.com"
  ------------------
  |  Branch (495:7): [True: 2.70k, False: 32.4k]
  ------------------
  496|  2.70k|			algo->usable = 0;
  497|  2.70k|		}
  498|  35.1k|	}
  499|  2.70k|}

cli_recv_msg_request_success:
  172|    351|void cli_recv_msg_request_success() {
  173|       |	/* We just mark off that we have received the reply,
  174|       |	 * so that we can report failure for later ones. */
  175|    351|	m_list_elem * iter = NULL;
  176|    351|	for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
  ------------------
  |  Branch (176:42): [True: 0, False: 351]
  ------------------
  177|      0|		struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
  178|      0|		if (!fwd->have_reply) {
  ------------------
  |  Branch (178:7): [True: 0, False: 0]
  ------------------
  179|      0|			fwd->have_reply = 1;
  180|      0|			if (fwd->listenport == 0) {
  ------------------
  |  Branch (180:8): [True: 0, False: 0]
  ------------------
  181|       |				/* The server should let us know which port was allocated if we requested port 0 */
  182|      0|				int allocport = buf_getint(ses.payload);
  183|      0|				if (allocport > 0) {
  ------------------
  |  Branch (183:9): [True: 0, False: 0]
  ------------------
  184|      0|					fwd->listenport = allocport;
  185|       |					dropbear_log(LOG_INFO, "Allocated port %d for remote forward to %s:%d", 
  186|      0|							allocport, fwd->connectaddr, fwd->connectport);
  187|      0|				}
  188|      0|			}
  189|      0|			return;
  190|      0|		}
  191|      0|	}
  192|    351|}
cli_recv_msg_request_failure:
  194|    195|void cli_recv_msg_request_failure() {
  195|    195|	m_list_elem *iter;
  196|    195|	for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
  ------------------
  |  Branch (196:42): [True: 0, False: 195]
  ------------------
  197|      0|		struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
  198|      0|		if (!fwd->have_reply) {
  ------------------
  |  Branch (198:7): [True: 0, False: 0]
  ------------------
  199|      0|			fwd->have_reply = 1;
  200|      0|			fwd_failed("Remote TCP forward request failed (port %d -> %s:%d)",
  201|      0|					fwd->listenport,
  202|      0|					fwd->connectaddr,
  203|      0|					fwd->connectport);
  204|      0|			return;
  205|      0|		}
  206|      0|	}
  207|    195|}
cli-tcpfwd.c:newtcpforwarded:
  231|    453|static int newtcpforwarded(struct Channel * channel) {
  232|       |
  233|    453|	char *origaddr = NULL;
  234|    453|	unsigned int origport;
  235|    453|	m_list_elem * iter = NULL;
  236|    453|	struct TCPFwdEntry *fwd = NULL;
  237|    453|	char portstring[NI_MAXSERV];
  238|    453|	int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
  ------------------
  |  |   33|    453|#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED    1
  ------------------
  239|       |
  240|    453|	origaddr = buf_getstring(ses.payload, NULL);
  241|    453|	origport = buf_getint(ses.payload);
  242|       |
  243|       |	/* Find which port corresponds. First try and match address as well as port,
  244|       |	in case they want to forward different ports separately ... */
  245|    453|	for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
  ------------------
  |  Branch (245:42): [True: 0, False: 453]
  ------------------
  246|      0|		fwd = (struct TCPFwdEntry*)iter->item;
  247|      0|		if (origport == fwd->listenport
  ------------------
  |  Branch (247:7): [True: 0, False: 0]
  ------------------
  248|      0|				&& strcmp(origaddr, fwd->listenaddr) == 0) {
  ------------------
  |  Branch (248:8): [True: 0, False: 0]
  ------------------
  249|      0|			break;
  250|      0|		}
  251|      0|	}
  252|       |
  253|    453|	if (!iter)
  ------------------
  |  Branch (253:6): [True: 449, False: 4]
  ------------------
  254|    449|	{
  255|       |		/* ... otherwise try to generically match the only forwarded port 
  256|       |		without address (also handles ::1 vs 127.0.0.1 vs localhost case).
  257|       |		rfc4254 is vague about the definition of "address that was connected" */
  258|    449|		for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
  ------------------
  |  Branch (258:43): [True: 0, False: 449]
  ------------------
  259|      0|			fwd = (struct TCPFwdEntry*)iter->item;
  260|      0|			if (origport == fwd->listenport) {
  ------------------
  |  Branch (260:8): [True: 0, False: 0]
  ------------------
  261|      0|				break;
  262|      0|			}
  263|      0|		}
  264|    449|	}
  265|       |
  266|       |
  267|    453|	if (iter == NULL || fwd == NULL) {
  ------------------
  |  Branch (267:6): [True: 453, False: 0]
  |  Branch (267:22): [True: 0, False: 0]
  ------------------
  268|       |		/* We didn't request forwarding on that port */
  269|    449|		cleantext(origaddr);
  270|    449|		dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"", 
  271|    449|                origaddr, origport);
  272|    449|		goto out;
  273|    449|	}
  274|       |
  275|      4|	snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
  276|      4|	channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done,
  277|      4|		channel, NULL, NULL, DROPBEAR_PRIO_NORMAL);
  278|       |
  279|      4|	err = SSH_OPEN_IN_PROGRESS;
  ------------------
  |  |   39|      4|#define SSH_OPEN_IN_PROGRESS					99
  ------------------
  280|       |
  281|    449|out:
  282|       |	m_free(origaddr);
  ------------------
  |  |   24|    449|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 449]
  |  |  ------------------
  ------------------
  283|    449|	TRACE(("leave newtcpdirect: err %d", err))
  284|    449|	return err;
  285|      4|}

buf_put_algolist_all:
  361|  21.6k|void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall) {
  362|  21.6k|	unsigned int i, len;
  363|  21.6k|	unsigned int donefirst = 0;
  364|  21.6k|	unsigned int startpos;
  365|       |
  366|  21.6k|	startpos = buf->pos;
  367|       |	/* Placeholder for length */
  368|  21.6k|	buf_putint(buf, 0); 
  369|   108k|	for (i = 0; localalgos[i].name != NULL; i++) {
  ------------------
  |  Branch (369:14): [True: 86.5k, False: 21.6k]
  ------------------
  370|  86.5k|		if (localalgos[i].usable || useall) {
  ------------------
  |  Branch (370:7): [True: 83.8k, False: 2.70k]
  |  Branch (370:31): [True: 0, False: 2.70k]
  ------------------
  371|  83.8k|			if (donefirst) {
  ------------------
  |  Branch (371:8): [True: 62.1k, False: 21.6k]
  ------------------
  372|  62.1k|				buf_putbyte(buf, ',');
  373|  62.1k|			}
  374|  83.8k|			donefirst = 1;
  375|  83.8k|			len = strlen(localalgos[i].name);
  376|  83.8k|			buf_putbytes(buf, (const unsigned char *) localalgos[i].name, len);
  377|  83.8k|		}
  378|  86.5k|	}
  379|       |	/* Fill out the length */
  380|  21.6k|	len = buf->pos - startpos - 4;
  381|  21.6k|	buf_setpos(buf, startpos);
  382|  21.6k|	buf_putint(buf, len);
  383|  21.6k|	TRACE(("algolist add %d '%.*s'", len, len, buf_getptr(buf, len)))
  384|  21.6k|	buf_incrwritepos(buf, len);
  385|  21.6k|}
buf_put_algolist:
  387|  21.6k|void buf_put_algolist(buffer * buf, const algo_type localalgos[]) {
  388|  21.6k|	buf_put_algolist_all(buf, localalgos, 0);
  389|  21.6k|}
buf_has_algo:
  433|  2.05k|int buf_has_algo(buffer *buf, const char *algo) {
  434|  2.05k|	unsigned char* algolist = NULL;
  435|  2.05k|	unsigned int orig_pos = buf->pos;
  436|  2.05k|	unsigned int len, remotecount, i;
  437|  2.05k|	const char *remotenames[MAX_PROPOSED_ALGO];
  438|  2.05k|	int ret = DROPBEAR_FAILURE;
  ------------------
  |  |  112|  2.05k|#define DROPBEAR_FAILURE -1
  ------------------
  439|       |
  440|  2.05k|	algolist = buf_getstring(buf, &len);
  441|  2.05k|	remotecount = MAX_PROPOSED_ALGO;
  ------------------
  |  |  237|  2.05k|#define MAX_PROPOSED_ALGO 50
  ------------------
  442|  2.05k|	get_algolist(algolist, len, remotenames, &remotecount);
  443|  6.17k|	for (i = 0; i < remotecount; i++)
  ------------------
  |  Branch (443:14): [True: 4.12k, False: 2.05k]
  ------------------
  444|  4.12k|	{
  445|  4.12k|		if (strcmp(remotenames[i], algo) == 0) {
  ------------------
  |  Branch (445:7): [True: 4, False: 4.12k]
  ------------------
  446|      4|			ret = DROPBEAR_SUCCESS;
  ------------------
  |  |  111|      4|#define DROPBEAR_SUCCESS 0
  ------------------
  447|      4|			break;
  448|      4|		}
  449|  4.12k|	}
  450|  2.05k|	if (algolist) {
  ------------------
  |  Branch (450:6): [True: 1.99k, False: 62]
  ------------------
  451|       |		m_free(algolist);
  ------------------
  |  |   24|  1.99k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1.99k]
  |  |  ------------------
  ------------------
  452|  1.99k|	}
  453|  2.05k|	buf_setpos(buf, orig_pos);
  454|  2.05k|	return ret;
  455|  2.05k|}
first_usable_algo:
  457|  5.40k|algo_type * first_usable_algo(algo_type algos[]) {
  458|  5.40k|	int i;
  459|  5.40k|	for (i = 0; algos[i].name != NULL; i++) {
  ------------------
  |  Branch (459:14): [True: 5.40k, False: 0]
  ------------------
  460|  5.40k|		if (algos[i].usable) {
  ------------------
  |  Branch (460:7): [True: 5.40k, False: 0]
  ------------------
  461|  5.40k|			return &algos[i];
  462|  5.40k|		}
  463|  5.40k|	}
  464|      0|	return NULL;
  465|  5.40k|}
buf_match_algo:
  473|  14.3k|		int kexguess2, int *goodguess) {
  474|  14.3k|	char * algolist = NULL;
  475|  14.3k|	const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
  476|  14.3k|	unsigned int len;
  477|  14.3k|	unsigned int remotecount, localcount, clicount, servcount, i, j;
  478|  14.3k|	algo_type * ret = NULL;
  479|  14.3k|	const char **clinames, **servnames;
  480|       |
  481|  14.3k|	if (goodguess) {
  ------------------
  |  Branch (481:6): [True: 3.79k, False: 10.5k]
  ------------------
  482|  3.79k|		*goodguess = 0;
  483|  3.79k|	}
  484|       |
  485|       |	/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
  486|  14.3k|	algolist = buf_getstring(buf, &len);
  487|  14.3k|	DEBUG3(("buf_match_algo: %s", algolist))
  488|  14.3k|	remotecount = MAX_PROPOSED_ALGO;
  ------------------
  |  |  237|  14.3k|#define MAX_PROPOSED_ALGO 50
  ------------------
  489|  14.3k|	get_algolist(algolist, len, remotenames, &remotecount);
  490|       |
  491|  74.1k|	for (i = 0; localalgos[i].name != NULL; i++) {
  ------------------
  |  Branch (491:14): [True: 59.7k, False: 14.3k]
  ------------------
  492|  59.7k|		if (localalgos[i].usable) {
  ------------------
  |  Branch (492:7): [True: 57.7k, False: 1.99k]
  ------------------
  493|  57.7k|			localnames[i] = localalgos[i].name;
  494|  57.7k|		} else {
  495|  1.99k|			localnames[i] = NULL;
  496|  1.99k|		}
  497|  59.7k|	}
  498|  14.3k|	localcount = i;
  499|       |
  500|  14.3k|	if (IS_DROPBEAR_SERVER) {
  ------------------
  |  |  381|  14.3k|#define IS_DROPBEAR_SERVER (ses.isserver == 1)
  |  |  ------------------
  |  |  |  Branch (381:28): [True: 0, False: 14.3k]
  |  |  ------------------
  ------------------
  501|      0|		clinames = remotenames;
  502|      0|		clicount = remotecount;
  503|      0|		servnames = localnames;
  504|      0|		servcount = localcount;
  505|  14.3k|	} else {
  506|  14.3k|		clinames = localnames;
  507|  14.3k|		clicount = localcount;
  508|  14.3k|		servnames = remotenames;
  509|  14.3k|		servcount = remotecount;
  510|  14.3k|	}
  511|       |
  512|       |	/* iterate and find the first match */
  513|  46.6k|	for (i = 0; i < clicount; i++) {
  ------------------
  |  Branch (513:14): [True: 46.4k, False: 255]
  ------------------
  514|  95.2k|		for (j = 0; j < servcount; j++) {
  ------------------
  |  Branch (514:15): [True: 62.9k, False: 32.2k]
  ------------------
  515|  62.9k|			if (!(servnames[j] && clinames[i])) {
  ------------------
  |  Branch (515:10): [True: 62.9k, False: 0]
  |  Branch (515:26): [True: 62.4k, False: 487]
  ------------------
  516|       |				/* unusable algos are NULL */
  517|    487|				continue;
  518|    487|			}
  519|  62.4k|			if (strcmp(servnames[j], clinames[i]) == 0) {
  ------------------
  |  Branch (519:8): [True: 14.1k, False: 48.3k]
  ------------------
  520|       |				/* set if it was a good guess */
  521|  14.1k|				if (goodguess != NULL) {
  ------------------
  |  Branch (521:9): [True: 3.59k, False: 10.5k]
  ------------------
  522|  3.59k|					if (kexguess2) {
  ------------------
  |  Branch (522:10): [True: 6, False: 3.58k]
  ------------------
  523|      6|						if (i == 0) {
  ------------------
  |  Branch (523:11): [True: 3, False: 3]
  ------------------
  524|      3|							*goodguess = 1;
  525|      3|						}
  526|  3.58k|					} else {
  527|  3.58k|						if (i == 0 && j == 0) {
  ------------------
  |  Branch (527:11): [True: 9, False: 3.57k]
  |  Branch (527:21): [True: 5, False: 4]
  ------------------
  528|      5|							*goodguess = 1;
  529|      5|						}
  530|  3.58k|					}
  531|  3.59k|				}
  532|       |				/* set the algo to return */
  533|  14.1k|				if (IS_DROPBEAR_SERVER) {
  ------------------
  |  |  381|  14.1k|#define IS_DROPBEAR_SERVER (ses.isserver == 1)
  |  |  ------------------
  |  |  |  Branch (381:28): [True: 0, False: 14.1k]
  |  |  ------------------
  ------------------
  534|      0|					ret = &localalgos[j];
  535|  14.1k|				} else {
  536|  14.1k|					ret = &localalgos[i];
  537|  14.1k|				}
  538|  14.1k|				goto out;
  539|  14.1k|			}
  540|  62.4k|		}
  541|  46.4k|	}
  542|       |
  543|  14.3k|out:
  544|       |	m_free(algolist);
  ------------------
  |  |   24|  14.3k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 14.3k]
  |  |  ------------------
  ------------------
  545|  14.3k|	return ret;
  546|  14.3k|}
common-algo.c:void_cipher:
   43|  85.1k|		unsigned long len, void* UNUSED(cipher_state)) {
   44|  85.1k|	if (in != out) {
  ------------------
  |  Branch (44:6): [True: 0, False: 85.1k]
  ------------------
   45|      0|		memmove(out, in, len);
   46|      0|	}
   47|  85.1k|	return CRYPT_OK;
   48|  85.1k|}
common-algo.c:get_algolist:
  396|  16.3k|				const char* *ret_list, unsigned int *ret_count) {
  397|  16.3k|	unsigned int max_count = *ret_count;
  398|  16.3k|	unsigned int i;
  399|       |
  400|  16.3k|	if (*ret_count == 0) {
  ------------------
  |  Branch (400:6): [True: 0, False: 16.3k]
  ------------------
  401|      0|		return;
  402|      0|	}
  403|  16.3k|	if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
  ------------------
  |  |  237|  16.3k|#define MAX_PROPOSED_ALGO 50
  ------------------
              	if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
  ------------------
  |  |  233|  16.3k|#define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't
  ------------------
  |  Branch (403:6): [True: 9, False: 16.3k]
  ------------------
  404|      9|		*ret_count = 0;
  405|      9|	}
  406|       |
  407|       |	/* ret_list will contain a list of the strings parsed out.
  408|       |	   We will have at least one string (even if it's just "") */
  409|  16.3k|	ret_list[0] = algolist;
  410|  16.3k|	*ret_count = 1;
  411|   219k|	for (i = 0; i < algolist_len; i++) {
  ------------------
  |  Branch (411:14): [True: 203k, False: 16.3k]
  ------------------
  412|   203k|		if (algolist[i] == '\0') {
  ------------------
  |  Branch (412:7): [True: 40, False: 203k]
  ------------------
  413|       |			/* someone is trying something strange */
  414|     40|			*ret_count = 0;
  415|     40|			return;
  416|     40|		}
  417|       |
  418|   203k|		if (algolist[i] == ',') {
  ------------------
  |  Branch (418:7): [True: 4.50k, False: 198k]
  ------------------
  419|  4.50k|			if (*ret_count >= max_count) {
  ------------------
  |  Branch (419:8): [True: 3, False: 4.50k]
  ------------------
  420|      3|				dropbear_exit("Too many remote algorithms");
  421|      0|				*ret_count = 0;
  422|      0|				return;
  423|      3|			}
  424|  4.50k|			algolist[i] = '\0';
  425|  4.50k|			ret_list[*ret_count] = &algolist[i+1];
  426|  4.50k|			(*ret_count)++;
  427|  4.50k|		}
  428|   203k|	}
  429|  16.3k|}

chaninitialise:
   70|  2.70k|void chaninitialise(const struct ChanType *chantypes[]) {
   71|       |
   72|       |	/* may as well create space for a single channel */
   73|  2.70k|	ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
   74|  2.70k|	ses.chansize = 1;
   75|  2.70k|	ses.channels[0] = NULL;
   76|  2.70k|	ses.chancount = 0;
   77|       |
   78|  2.70k|	ses.chantypes = chantypes;
   79|       |
   80|  2.70k|#if DROPBEAR_LISTENERS
   81|  2.70k|	listeners_initialise();
   82|  2.70k|#endif
   83|       |
   84|  2.70k|}
chancleanup:
   87|  2.70k|void chancleanup() {
   88|       |
   89|  2.70k|	unsigned int i;
   90|       |
   91|  2.70k|	TRACE(("enter chancleanup"))
   92|  5.40k|	for (i = 0; i < ses.chansize; i++) {
  ------------------
  |  Branch (92:14): [True: 2.70k, False: 2.70k]
  ------------------
   93|  2.70k|		if (ses.channels[i] != NULL) {
  ------------------
  |  Branch (93:7): [True: 4, False: 2.70k]
  ------------------
   94|      4|			TRACE(("channel %d closing", i))
   95|      4|			remove_channel(ses.channels[i]);
   96|      4|		}
   97|  2.70k|	}
   98|       |	m_free(ses.channels);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
   99|  2.70k|	TRACE(("leave chancleanup"))
  100|  2.70k|}
getchannel:
  194|    302|struct Channel* getchannel() {
  195|       |	return getchannel_msg(NULL);
  196|    302|}
channelio:
  199|   136k|void channelio(const fd_set *readfds, const fd_set *writefds) {
  200|       |
  201|       |	/* Listeners such as TCP, X11, agent-auth */
  202|   136k|	struct Channel *channel;
  203|   136k|	unsigned int i;
  204|       |
  205|       |	/* foreach channel */
  206|   272k|	for (i = 0; i < ses.chansize; i++) {
  ------------------
  |  Branch (206:14): [True: 136k, False: 136k]
  ------------------
  207|       |		/* Close checking only needs to occur for channels that had IO events */
  208|   136k|		int do_check_close = 0;
  209|       |
  210|   136k|		channel = ses.channels[i];
  211|   136k|		if (channel == NULL) {
  ------------------
  |  Branch (211:7): [True: 136k, False: 0]
  ------------------
  212|       |			/* only process in-use channels */
  213|   136k|			continue;
  214|   136k|		}
  215|       |
  216|       |		/* read data and send it over the wire */
  217|      0|		if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
  ------------------
  |  Branch (217:7): [True: 0, False: 0]
  |  Branch (217:31): [True: 0, False: 0]
  ------------------
  218|      0|			TRACE(("send normal readfd"))
  219|      0|			send_msg_channel_data(channel, 0);
  220|      0|			do_check_close = 1;
  221|      0|		}
  222|       |
  223|       |		/* read stderr data and send it over the wire */
  224|      0|		if (ERRFD_IS_READ(channel) && channel->errfd >= 0 
  ------------------
  |  |   59|      0|#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
  |  |  ------------------
  |  |  |  Branch (59:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (224:33): [True: 0, False: 0]
  ------------------
  225|      0|			&& FD_ISSET(channel->errfd, readfds)) {
  ------------------
  |  Branch (225:7): [True: 0, False: 0]
  ------------------
  226|      0|				TRACE(("send normal errfd"))
  227|      0|				send_msg_channel_data(channel, 1);
  228|      0|			do_check_close = 1;
  229|      0|		}
  230|       |
  231|       |		/* write to program/pipe stdin */
  232|      0|		if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
  ------------------
  |  Branch (232:7): [True: 0, False: 0]
  |  Branch (232:32): [True: 0, False: 0]
  ------------------
  233|      0|			writechannel(channel, channel->writefd, channel->writebuf, NULL, NULL);
  234|      0|			do_check_close = 1;
  235|      0|		}
  236|       |		
  237|       |		/* stderr for client mode */
  238|      0|		if (ERRFD_IS_WRITE(channel)
  ------------------
  |  |   60|      0|#define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
  |  |  ------------------
  |  |  |  |   59|      0|#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
  |  |  ------------------
  |  |  |  Branch (60:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  239|      0|				&& channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
  ------------------
  |  Branch (239:8): [True: 0, False: 0]
  |  Branch (239:31): [True: 0, False: 0]
  ------------------
  240|      0|			writechannel(channel, channel->errfd, channel->extrabuf, NULL, NULL);
  241|      0|			do_check_close = 1;
  242|      0|		}
  243|       |
  244|      0|		if (ses.channel_signal_pending) {
  ------------------
  |  Branch (244:7): [True: 0, False: 0]
  ------------------
  245|       |			/* SIGCHLD can change channel state for server sessions */
  246|      0|			do_check_close = 1;
  247|      0|		}
  248|       |	
  249|       |		/* handle any channel closing etc */
  250|      0|		if (do_check_close) {
  ------------------
  |  Branch (250:7): [True: 0, False: 0]
  ------------------
  251|      0|			check_close(channel);
  252|      0|		}
  253|      0|	}
  254|       |
  255|   136k|#if DROPBEAR_LISTENERS
  256|   136k|	handle_listeners(readfds);
  257|   136k|#endif
  258|   136k|}
setchannelfds:
  542|   139k|void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) {
  543|       |	
  544|   139k|	unsigned int i;
  545|   139k|	struct Channel * channel;
  546|       |	
  547|   278k|	for (i = 0; i < ses.chansize; i++) {
  ------------------
  |  Branch (547:14): [True: 139k, False: 139k]
  ------------------
  548|       |
  549|   139k|		channel = ses.channels[i];
  550|   139k|		if (channel == NULL) {
  ------------------
  |  Branch (550:7): [True: 139k, False: 0]
  ------------------
  551|   139k|			continue;
  552|   139k|		}
  553|       |
  554|       |		/* Stuff to put over the wire. 
  555|       |		Avoid queueing data to send if we're in the middle of a 
  556|       |		key re-exchange (!dataallowed), but still read from the 
  557|       |		FD if there's the possibility of "~."" to kill an 
  558|       |		interactive session (the read_mangler) */
  559|      0|		if (channel->transwindow > 0
  ------------------
  |  Branch (559:7): [True: 0, False: 0]
  ------------------
  560|      0|		   && ((ses.dataallowed && allow_reads) || channel->read_mangler)) {
  ------------------
  |  Branch (560:11): [True: 0, False: 0]
  |  Branch (560:30): [True: 0, False: 0]
  |  Branch (560:46): [True: 0, False: 0]
  ------------------
  561|       |
  562|      0|			if (channel->readfd >= 0) {
  ------------------
  |  Branch (562:8): [True: 0, False: 0]
  ------------------
  563|      0|				FD_SET(channel->readfd, readfds);
  564|      0|			}
  565|       |			
  566|      0|			if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
  ------------------
  |  |   59|      0|#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
  |  |  ------------------
  |  |  |  Branch (59:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (566:34): [True: 0, False: 0]
  ------------------
  567|      0|					FD_SET(channel->errfd, readfds);
  568|      0|			}
  569|      0|		}
  570|       |
  571|       |		/* Stuff from the wire */
  572|      0|		if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
  ------------------
  |  Branch (572:7): [True: 0, False: 0]
  |  Branch (572:32): [True: 0, False: 0]
  ------------------
  573|      0|				FD_SET(channel->writefd, writefds);
  574|      0|		}
  575|       |
  576|      0|		if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0 
  ------------------
  |  |   60|      0|#define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
  |  |  ------------------
  |  |  |  |   59|      0|#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
  |  |  ------------------
  |  |  |  Branch (60:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (576:34): [True: 0, False: 0]
  ------------------
  577|      0|				&& cbuf_getused(channel->extrabuf) > 0) {
  ------------------
  |  Branch (577:8): [True: 0, False: 0]
  ------------------
  578|      0|				FD_SET(channel->errfd, writefds);
  579|      0|		}
  580|       |
  581|      0|	} /* foreach channel */
  582|       |
  583|   139k|#if DROPBEAR_LISTENERS
  584|   139k|	set_listener_fds(readfds);
  585|   139k|#endif
  586|       |
  587|   139k|}
recv_msg_channel_eof:
  592|     50|void recv_msg_channel_eof() {
  593|       |
  594|     50|	struct Channel * channel;
  595|       |
  596|     50|	TRACE(("enter recv_msg_channel_eof"))
  597|       |
  598|     50|	channel = getchannel_msg("EOF");
  599|       |
  600|     50|	channel->recv_eof = 1;
  601|       |
  602|     50|	check_close(channel);
  603|     50|	TRACE(("leave recv_msg_channel_eof"))
  604|     50|}
recv_msg_channel_close:
  608|     50|void recv_msg_channel_close() {
  609|       |
  610|     50|	struct Channel * channel;
  611|       |
  612|     50|	TRACE(("enter recv_msg_channel_close"))
  613|       |
  614|     50|	channel = getchannel_msg("Close");
  615|       |
  616|     50|	channel->recv_eof = 1;
  617|     50|	channel->recv_close = 1;
  618|       |
  619|     50|	check_close(channel);
  620|     50|	TRACE(("leave recv_msg_channel_close"))
  621|     50|}
recv_msg_channel_request:
  669|     49|void recv_msg_channel_request() {
  670|       |
  671|     49|	struct Channel *channel;
  672|       |
  673|     49|	channel = getchannel();
  674|       |
  675|     49|	TRACE(("enter recv_msg_channel_request %p", (void*)channel))
  676|       |
  677|     49|	if (channel->type->reqhandler) {
  ------------------
  |  Branch (677:6): [True: 0, False: 49]
  ------------------
  678|      0|		channel->type->reqhandler(channel);
  679|     49|	} else {
  680|     49|		int wantreply;
  681|     49|		buf_eatstring(ses.payload);
  682|     49|		wantreply = buf_getbool(ses.payload);
  683|     49|		if (wantreply) {
  ------------------
  |  Branch (683:7): [True: 0, False: 49]
  ------------------
  684|      0|			send_msg_channel_failure(channel);
  685|      0|		}
  686|     49|	}
  687|       |
  688|     49|	TRACE(("leave recv_msg_channel_request"))
  689|       |
  690|     49|}
recv_msg_channel_data:
  776|     53|void recv_msg_channel_data() {
  777|       |
  778|     53|	struct Channel *channel;
  779|       |
  780|     53|	channel = getchannel();
  781|       |
  782|     53|	common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
  783|     53|}
recv_msg_channel_window_adjust:
  858|     55|void recv_msg_channel_window_adjust() {
  859|       |
  860|     55|	struct Channel * channel;
  861|     55|	unsigned int incr, newwin;
  862|       |	
  863|     55|	channel = getchannel();
  864|       |	
  865|     55|	incr = buf_getint(ses.payload);
  866|     55|	TRACE(("received window increment %u", incr))
  867|       |	
  868|     55|	newwin = channel->transwindow + incr;
  869|     55|	if (newwin < channel->transwindow) {
  ------------------
  |  Branch (869:6): [True: 0, False: 55]
  ------------------
  870|       |		/* Integer overflow, clamp it at maximum.
  871|       |		 * Behaviour may be unexpected, senders MUST NOT overflow per rfc4254. */
  872|      0|		TRACE(("overflow window, prev %u", channel->transwindow));
  873|      0|		newwin = 0xffffffff;
  874|      0|	}
  875|     55|	channel->transwindow = newwin;
  876|     55|}
recv_msg_channel_open:
  894|  1.63k|void recv_msg_channel_open() {
  895|       |
  896|  1.63k|	char *type;
  897|  1.63k|	unsigned int typelen;
  898|  1.63k|	unsigned int remotechan, transwindow, transmaxpacket;
  899|  1.63k|	struct Channel *channel;
  900|  1.63k|	const struct ChanType **cp;
  901|  1.63k|	const struct ChanType *chantype;
  902|  1.63k|	unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
  ------------------
  |  |   35|  1.63k|#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE           3
  ------------------
  903|  1.63k|	int ret;
  904|       |
  905|       |
  906|  1.63k|	TRACE(("enter recv_msg_channel_open"))
  907|       |
  908|       |	/* get the packet contents */
  909|  1.63k|	type = buf_getstring(ses.payload, &typelen);
  910|       |
  911|  1.63k|	remotechan = buf_getint(ses.payload);
  912|  1.63k|	transwindow = buf_getint(ses.payload);
  913|  1.63k|	transmaxpacket = buf_getint(ses.payload);
  914|  1.63k|	transmaxpacket = MIN(transmaxpacket, TRANS_MAX_PAYLOAD_LEN);
  ------------------
  |  Branch (914:19): [True: 341, False: 1.29k]
  ------------------
  915|       |
  916|       |	/* figure what type of packet it is */
  917|  1.63k|	if (typelen > MAX_NAME_LEN) {
  ------------------
  |  |  233|  1.63k|#define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't
  ------------------
  |  Branch (917:6): [True: 199, False: 1.43k]
  ------------------
  918|    199|		goto failure;
  919|    199|	}
  920|       |
  921|       |	/* Get the channel type. Client and server style invokation will set up a
  922|       |	 * different list for ses.chantypes at startup. We just iterate through
  923|       |	 * this list and find the matching name */
  924|  1.43k|	for (cp = &ses.chantypes[0], chantype = (*cp); 
  925|  3.18k|			chantype != NULL;
  ------------------
  |  Branch (925:4): [True: 2.39k, False: 787]
  ------------------
  926|  2.39k|			cp++, chantype = (*cp)) {
  927|  2.39k|		if (strcmp(type, chantype->name) == 0) {
  ------------------
  |  Branch (927:7): [True: 647, False: 1.75k]
  ------------------
  928|    647|			break;
  929|    647|		}
  930|  2.39k|	}
  931|       |
  932|  1.43k|	if (chantype == NULL) {
  ------------------
  |  Branch (932:6): [True: 779, False: 655]
  ------------------
  933|    779|		TRACE(("No matching type for '%s'", type))
  934|    779|		goto failure;
  935|    779|	}
  936|       |
  937|    655|	TRACE(("matched type '%s'", type))
  938|       |
  939|       |	/* create the channel */
  940|    655|	channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
  941|       |
  942|    655|	if (channel == NULL) {
  ------------------
  |  Branch (942:6): [True: 0, False: 655]
  ------------------
  943|      0|		TRACE(("newchannel returned NULL"))
  944|      0|		errtype = SSH_OPEN_RESOURCE_SHORTAGE;
  ------------------
  |  |   36|      0|#define SSH_OPEN_RESOURCE_SHORTAGE              4
  ------------------
  945|      0|		goto failure;
  946|      0|	}
  947|       |
  948|    655|	if (channel->type->inithandler) {
  ------------------
  |  Branch (948:6): [True: 647, False: 8]
  ------------------
  949|    647|		ret = channel->type->inithandler(channel);
  950|    647|		if (ret == SSH_OPEN_IN_PROGRESS) {
  ------------------
  |  |   39|    647|#define SSH_OPEN_IN_PROGRESS					99
  ------------------
  |  Branch (950:7): [True: 0, False: 647]
  ------------------
  951|       |			/* We'll send the confirmation later */
  952|      0|			goto cleanup;
  953|      0|		}
  954|    647|		if (ret > 0) {
  ------------------
  |  Branch (954:7): [True: 643, False: 4]
  ------------------
  955|    643|			errtype = ret;
  956|    643|			remove_channel(channel);
  957|    643|			TRACE(("inithandler returned failure %d", ret))
  958|    643|			goto failure;
  959|    643|		}
  960|    647|	}
  961|       |
  962|     12|	update_channel_prio();
  963|       |
  964|       |	/* success */
  965|     12|	send_msg_channel_open_confirmation(channel, channel->recvwindow,
  966|     12|			channel->recvmaxpacket);
  967|     12|	goto cleanup;
  968|       |
  969|  1.62k|failure:
  970|  1.62k|	TRACE(("recv_msg_channel_open failure"))
  971|  1.62k|	send_msg_channel_open_failure(remotechan, errtype, "", "");
  972|       |
  973|  1.62k|cleanup:
  974|  1.62k|	m_free(type);
  ------------------
  |  |   24|  1.62k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1.62k]
  |  |  ------------------
  ------------------
  975|       |
  976|  1.62k|	TRACE(("leave recv_msg_channel_open"))
  977|  1.62k|}
recv_msg_channel_open_confirmation:
 1138|     51|void recv_msg_channel_open_confirmation() {
 1139|       |
 1140|     51|	struct Channel * channel;
 1141|     51|	int ret;
 1142|       |
 1143|     51|	TRACE(("enter recv_msg_channel_open_confirmation"))
 1144|       |
 1145|     51|	channel = getchannel();
 1146|       |
 1147|     51|	if (!channel->await_open) {
  ------------------
  |  Branch (1147:6): [True: 0, False: 51]
  ------------------
 1148|      0|		dropbear_exit("Unexpected channel reply");
 1149|      0|	}
 1150|     51|	channel->await_open = 0;
 1151|       |
 1152|     51|	channel->remotechan =  buf_getint(ses.payload);
 1153|     51|	channel->transwindow = buf_getint(ses.payload);
 1154|     51|	channel->transmaxpacket = buf_getint(ses.payload);
 1155|       |	
 1156|     51|	TRACE(("new chan remote %d local %d", 
 1157|     51|				channel->remotechan, channel->index))
 1158|       |
 1159|       |	/* Run the inithandler callback */
 1160|     51|	if (channel->type->inithandler) {
  ------------------
  |  Branch (1160:6): [True: 0, False: 51]
  ------------------
 1161|      0|		ret = channel->type->inithandler(channel);
 1162|      0|		if (ret > 0) {
  ------------------
  |  Branch (1162:7): [True: 0, False: 0]
  ------------------
 1163|      0|			remove_channel(channel);
 1164|      0|			TRACE(("inithandler returned failure %d", ret))
 1165|      0|			return;
 1166|      0|		}
 1167|      0|	}
 1168|       |
 1169|     51|	update_channel_prio();
 1170|       |
 1171|     51|	TRACE(("leave recv_msg_channel_open_confirmation"))
 1172|     51|}
recv_msg_channel_open_failure:
 1175|     52|void recv_msg_channel_open_failure() {
 1176|       |
 1177|     52|	struct Channel * channel;
 1178|       |
 1179|     52|	channel = getchannel();
 1180|       |
 1181|     52|	if (!channel->await_open) {
  ------------------
  |  Branch (1181:6): [True: 0, False: 52]
  ------------------
 1182|      0|		dropbear_exit("Unexpected channel reply");
 1183|      0|	}
 1184|     52|	channel->await_open = 0;
 1185|       |
 1186|     52|	remove_channel(channel);
 1187|     52|}
send_msg_request_failure:
 1196|    670|void send_msg_request_failure() {
 1197|    670|	CHECKCLEARTOWRITE();
 1198|    670|	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
  ------------------
  |  |   65|    670|#define SSH_MSG_REQUEST_FAILURE                 82
  ------------------
 1199|    670|	encrypt_packet();
 1200|    670|}
common-channel.c:getchannel_msg:
  179|    402|static struct Channel* getchannel_msg(const char* kind) {
  180|       |
  181|    402|	unsigned int chan;
  182|       |
  183|    402|	chan = buf_getint(ses.payload);
  184|    402|	if (chan >= ses.chansize || ses.channels[chan] == NULL) {
  ------------------
  |  Branch (184:6): [True: 394, False: 8]
  |  Branch (184:30): [True: 8, False: 0]
  ------------------
  185|    399|		if (kind) {
  ------------------
  |  Branch (185:7): [True: 98, False: 301]
  ------------------
  186|     98|			dropbear_exit("%s for unknown channel %d", kind, chan);
  187|    301|		} else {
  188|    301|			dropbear_exit("Unknown channel %d", chan);
  189|    301|		}
  190|    399|	}
  191|      3|	return ses.channels[chan];
  192|    402|}
common-channel.c:remove_channel:
  625|    647|static void remove_channel(struct Channel * channel) {
  626|       |
  627|    647|	TRACE(("enter remove_channel"))
  628|    647|	TRACE(("channel index is %d", channel->index))
  629|       |
  630|    647|	cbuf_free(channel->writebuf);
  631|    647|	channel->writebuf = NULL;
  632|       |
  633|    647|	if (channel->extrabuf) {
  ------------------
  |  Branch (633:6): [True: 0, False: 647]
  ------------------
  634|      0|		cbuf_free(channel->extrabuf);
  635|      0|		channel->extrabuf = NULL;
  636|      0|	}
  637|       |
  638|       |
  639|    647|	if (IS_DROPBEAR_SERVER || (channel->writefd != STDOUT_FILENO)) {
  ------------------
  |  |  381|  1.29k|#define IS_DROPBEAR_SERVER (ses.isserver == 1)
  |  |  ------------------
  |  |  |  Branch (381:28): [True: 0, False: 647]
  |  |  ------------------
  ------------------
  |  Branch (639:28): [True: 647, False: 0]
  ------------------
  640|       |		/* close the FDs in case they haven't been done
  641|       |		 * yet (they might have been shutdown etc) */
  642|    647|		TRACE(("CLOSE writefd %d", channel->writefd))
  643|    647|		m_close(channel->writefd);
  644|    647|		TRACE(("CLOSE readfd %d", channel->readfd))
  645|    647|		m_close(channel->readfd);
  646|    647|		TRACE(("CLOSE errfd %d", channel->errfd))
  647|    647|		m_close(channel->errfd);
  648|    647|	}
  649|       |
  650|    647|	if (channel->type->cleanup) {
  ------------------
  |  Branch (650:6): [True: 0, False: 647]
  ------------------
  651|      0|		channel->type->cleanup(channel);
  652|      0|	}
  653|       |
  654|    647|	if (channel->conn_pending) {
  ------------------
  |  Branch (654:6): [True: 0, False: 647]
  ------------------
  655|      0|		cancel_connect(channel->conn_pending);
  656|      0|	}
  657|       |
  658|    647|	ses.channels[channel->index] = NULL;
  659|    647|	m_free(channel);
  ------------------
  |  |   24|    647|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 647]
  |  |  ------------------
  ------------------
  660|    647|	ses.chancount--;
  661|       |
  662|    647|	update_channel_prio();
  663|       |
  664|    647|	TRACE(("leave remove_channel"))
  665|    647|}
common-channel.c:newchannel:
  108|    647|		unsigned int transwindow, unsigned int transmaxpacket) {
  109|       |
  110|    647|	struct Channel * newchan;
  111|    647|	unsigned int i, j;
  112|       |
  113|    647|	TRACE(("enter newchannel"))
  114|       |	
  115|       |	/* first see if we can use existing channels */
  116|    647|	for (i = 0; i < ses.chansize; i++) {
  ------------------
  |  Branch (116:14): [True: 647, False: 0]
  ------------------
  117|    647|		if (ses.channels[i] == NULL) {
  ------------------
  |  Branch (117:7): [True: 647, False: 0]
  ------------------
  118|    647|			break;
  119|    647|		}
  120|    647|	}
  121|       |
  122|       |	/* otherwise extend the list */
  123|    647|	if (i == ses.chansize) {
  ------------------
  |  Branch (123:6): [True: 0, False: 647]
  ------------------
  124|      0|		if (ses.chansize >= MAX_CHANNELS) {
  ------------------
  |  |  250|      0|#define MAX_CHANNELS 1000 /* simple mem restriction, includes each tcp/x11
  ------------------
  |  Branch (124:7): [True: 0, False: 0]
  ------------------
  125|      0|			TRACE(("leave newchannel: max chans reached"))
  126|      0|			return NULL;
  127|      0|		}
  128|       |
  129|       |		/* extend the channels */
  130|      0|		ses.channels = (struct Channel**)m_realloc(ses.channels,
  131|      0|				(ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
  ------------------
  |  |   41|      0|#define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */
  ------------------
  132|       |
  133|      0|		ses.chansize += CHAN_EXTEND_SIZE;
  ------------------
  |  |   41|      0|#define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */
  ------------------
  134|       |
  135|       |		/* set the new channels to null */
  136|      0|		for (j = i; j < ses.chansize; j++) {
  ------------------
  |  Branch (136:15): [True: 0, False: 0]
  ------------------
  137|      0|			ses.channels[j] = NULL;
  138|      0|		}
  139|       |
  140|      0|	}
  141|       |	
  142|    647|	newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
  143|    647|	newchan->type = type;
  144|    647|	newchan->index = i;
  145|    647|	newchan->sent_close = newchan->recv_close = 0;
  146|    647|	newchan->sent_eof = newchan->recv_eof = 0;
  147|       |
  148|    647|	newchan->remotechan = remotechan;
  149|    647|	newchan->transwindow = transwindow;
  150|    647|	newchan->transmaxpacket = transmaxpacket;
  151|       |	
  152|    647|	newchan->typedata = NULL;
  153|    647|	newchan->writefd = FD_UNINIT;
  ------------------
  |  |   56|    647|#define FD_UNINIT (-2)
  ------------------
  154|    647|	newchan->readfd = FD_UNINIT;
  ------------------
  |  |   56|    647|#define FD_UNINIT (-2)
  ------------------
  155|    647|	newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
  ------------------
  |  |   57|    647|#define FD_CLOSED (-1)
  ------------------
  156|    647|	newchan->await_open = 0;
  157|       |
  158|    647|	newchan->writebuf = cbuf_new(opts.recv_window);
  159|    647|	newchan->recvwindow = opts.recv_window;
  160|       |
  161|    647|	newchan->extrabuf = NULL; /* The user code can set it up */
  162|    647|	newchan->recvdonelen = 0;
  163|    647|	newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
  ------------------
  |  |   67|    647|#define RECV_MAX_CHANNEL_DATA_LEN (RECV_MAX_PAYLOAD_LEN-(1+4+4))
  |  |  ------------------
  |  |  |  |  555|    647|#define RECV_MAX_PAYLOAD_LEN 32768
  |  |  ------------------
  ------------------
  164|       |
  165|    647|	newchan->prio = DROPBEAR_PRIO_NORMAL;
  166|       |
  167|    647|	ses.channels[i] = newchan;
  168|    647|	ses.chancount++;
  169|       |
  170|    647|	TRACE(("leave newchannel"))
  171|       |
  172|    647|	return newchan;
  173|    647|}
common-channel.c:send_msg_channel_open_failure:
 1017|  1.62k|		int reason, const char *text, const char *lang) {
 1018|       |
 1019|  1.62k|	TRACE(("enter send_msg_channel_open_failure"))
 1020|  1.62k|	CHECKCLEARTOWRITE();
 1021|       |	
 1022|  1.62k|	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
  ------------------
  |  |   68|  1.62k|#define SSH_MSG_CHANNEL_OPEN_FAILURE            92
  ------------------
 1023|  1.62k|	buf_putint(ses.writepayload, remotechan);
 1024|  1.62k|	buf_putint(ses.writepayload, reason);
 1025|  1.62k|	buf_putstring(ses.writepayload, text, strlen(text));
 1026|  1.62k|	buf_putstring(ses.writepayload, lang, strlen(lang));
 1027|       |
 1028|  1.62k|	encrypt_packet();
 1029|  1.62k|	TRACE(("leave send_msg_channel_open_failure"))
 1030|  1.62k|}

send_msg_kexinit:
   51|  2.70k|void send_msg_kexinit() {
   52|       |
   53|  2.70k|	CHECKCLEARTOWRITE();
   54|  2.70k|	buf_putbyte(ses.writepayload, SSH_MSG_KEXINIT);
  ------------------
  |  |   36|  2.70k|#define SSH_MSG_KEXINIT                20
  ------------------
   55|       |
   56|       |	/* cookie */
   57|  2.70k|	genrandom(buf_getwriteptr(ses.writepayload, 16), 16);
   58|  2.70k|	buf_incrwritepos(ses.writepayload, 16);
   59|       |
   60|       |	/* kex algos */
   61|  2.70k|	buf_put_algolist(ses.writepayload, sshkex);
   62|       |
   63|       |	/* server_host_key_algorithms */
   64|  2.70k|	buf_put_algolist(ses.writepayload, sigalgs);
   65|       |
   66|       |	/* encryption_algorithms_client_to_server */
   67|  2.70k|	buf_put_algolist(ses.writepayload, sshciphers);
   68|       |
   69|       |	/* encryption_algorithms_server_to_client */
   70|  2.70k|	buf_put_algolist(ses.writepayload, sshciphers);
   71|       |
   72|       |	/* mac_algorithms_client_to_server */
   73|  2.70k|	buf_put_algolist(ses.writepayload, sshhashes);
   74|       |
   75|       |	/* mac_algorithms_server_to_client */
   76|  2.70k|	buf_put_algolist(ses.writepayload, sshhashes);
   77|       |
   78|       |
   79|       |	/* compression_algorithms_client_to_server */
   80|  2.70k|	buf_put_algolist(ses.writepayload, ses.compress_algos_c2s);
   81|       |
   82|       |	/* compression_algorithms_server_to_client */
   83|  2.70k|	buf_put_algolist(ses.writepayload, ses.compress_algos_s2c);
   84|       |
   85|       |	/* languages_client_to_server */
   86|  2.70k|	buf_putstring(ses.writepayload, "", 0);
   87|       |
   88|       |	/* languages_server_to_client */
   89|  2.70k|	buf_putstring(ses.writepayload, "", 0);
   90|       |
   91|       |	/* first_kex_packet_follows */
   92|  2.70k|	buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL));
   93|       |
   94|       |	/* reserved unit32 */
   95|  2.70k|	buf_putint(ses.writepayload, 0);
   96|       |
   97|       |	/* set up transmitted kex packet buffer for hashing. 
   98|       |	 * This is freed after the end of the kex */
   99|  2.70k|	ses.transkexinit = buf_newcopy(ses.writepayload);
  100|       |
  101|  2.70k|	encrypt_packet();
  102|  2.70k|	ses.dataallowed = 0; /* don't send other packets during kex */
  103|       |
  104|  2.70k|	ses.kexstate.sentkexinit = 1;
  105|       |
  106|  2.70k|	ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
  107|       |
  108|  2.70k|	if (ses.send_kex_first_guess) {
  ------------------
  |  Branch (108:6): [True: 2.70k, False: 0]
  ------------------
  109|  2.70k|		ses.newkeys->algo_kex = first_usable_algo(sshkex)->data;
  110|  2.70k|		ses.newkeys->algo_signature = first_usable_algo(sigalgs)->val;
  111|  2.70k|		ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
  112|  2.70k|		ses.send_kex_first_guess();
  113|  2.70k|	}
  114|       |
  115|  2.70k|	TRACE(("DATAALLOWED=0"))
  116|  2.70k|	TRACE(("-> KEXINIT"))
  117|       |
  118|  2.70k|}
recv_msg_newkeys:
  189|  1.08k|void recv_msg_newkeys() {
  190|       |
  191|  1.08k|	TRACE(("enter recv_msg_newkeys"))
  192|       |
  193|  1.08k|	ses.kexstate.recvnewkeys = 1;
  194|  1.08k|	switch_keys();
  195|       |
  196|  1.08k|	if (ses.kexstate.strict_kex) {
  ------------------
  |  Branch (196:6): [True: 0, False: 1.08k]
  ------------------
  197|      0|		ses.recvseq = 0;
  198|      0|	}
  199|  1.08k|	ses.kexstate.recvfirstnewkeys = 1;
  200|       |
  201|  1.08k|	TRACE(("leave recv_msg_newkeys"))
  202|  1.08k|}
kexfirstinitialise:
  230|  2.70k|void kexfirstinitialise() {
  231|  2.70k|	kex_setup_compress();
  232|  2.70k|	kexinitialise();
  233|  2.70k|}
recv_msg_kexinit:
  492|  2.06k|void recv_msg_kexinit() {
  493|       |	
  494|  2.06k|	unsigned int kexhashbuf_len = 0;
  495|  2.06k|	unsigned int remote_ident_len = 0;
  496|  2.06k|	unsigned int local_ident_len = 0;
  497|       |
  498|  2.06k|	TRACE(("<- KEXINIT"))
  499|  2.06k|	TRACE(("enter recv_msg_kexinit"))
  500|       |	
  501|  2.06k|	if (!ses.kexstate.sentkexinit) {
  ------------------
  |  Branch (501:6): [True: 0, False: 2.06k]
  ------------------
  502|       |		/* we need to send a kex packet */
  503|      0|		send_msg_kexinit();
  504|      0|		TRACE(("continue recv_msg_kexinit: sent kexinit"))
  505|      0|	}
  506|       |
  507|       |	/* "Once a party has sent a SSH_MSG_KEXINIT message ...
  508|       |	further SSH_MSG_KEXINIT messages MUST NOT be sent" */
  509|  2.06k|	if (ses.kexstate.recvkexinit) {
  ------------------
  |  Branch (509:6): [True: 1, False: 2.06k]
  ------------------
  510|      1|		dropbear_exit("Unexpected KEXINIT");
  511|      1|	}
  512|       |
  513|       |	/* start the kex hash */
  514|  2.06k|	local_ident_len = strlen(LOCAL_IDENT);
  ------------------
  |  |   14|  2.06k|#define LOCAL_IDENT "SSH-2.0-dropbear" IDENT_VERSION_PART
  |  |  ------------------
  |  |  |  |   12|  2.06k|#define IDENT_VERSION_PART "_" DROPBEAR_VERSION
  |  |  |  |  ------------------
  |  |  |  |  |  |    7|  2.06k|#define DROPBEAR_VERSION "2026.91"
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  515|  2.06k|	remote_ident_len = strlen(ses.remoteident);
  516|       |
  517|  2.06k|	kexhashbuf_len = local_ident_len + remote_ident_len
  518|  2.06k|		+ ses.transkexinit->len + ses.payload->len
  519|  2.06k|		+ KEXHASHBUF_MAX_INTS;
  ------------------
  |  |  290|  2.06k|#define KEXHASHBUF_MAX_INTS (MAX_PUBKEY_SIZE + MAX_KEX_PARTS)
  |  |  ------------------
  |  |  |  |  261|  2.06k|#define MAX_PUBKEY_SIZE 600
  |  |  ------------------
  |  |               #define KEXHASHBUF_MAX_INTS (MAX_PUBKEY_SIZE + MAX_KEX_PARTS)
  |  |  ------------------
  |  |  |  |  274|  2.06k|#define MAX_KEX_PARTS (2*4 + 1184 + 1088 + 32*2 + 68)
  |  |  ------------------
  ------------------
  520|       |
  521|  2.06k|	ses.kexhashbuf = buf_new(kexhashbuf_len);
  522|       |
  523|  2.06k|	if (IS_DROPBEAR_CLIENT) {
  ------------------
  |  |  382|  2.06k|#define IS_DROPBEAR_CLIENT (ses.isserver == 0)
  |  |  ------------------
  |  |  |  Branch (382:28): [True: 2.06k, False: 0]
  |  |  ------------------
  ------------------
  524|       |
  525|       |		/* read the peer's choice of algos */
  526|  2.06k|		read_kex_algos();
  527|       |
  528|       |		/* V_C, the client's version string (CR and NL excluded) */
  529|  2.06k|		buf_putstring(ses.kexhashbuf, LOCAL_IDENT, local_ident_len);
  ------------------
  |  |   14|  2.06k|#define LOCAL_IDENT "SSH-2.0-dropbear" IDENT_VERSION_PART
  |  |  ------------------
  |  |  |  |   12|  2.06k|#define IDENT_VERSION_PART "_" DROPBEAR_VERSION
  |  |  |  |  ------------------
  |  |  |  |  |  |    7|  2.06k|#define DROPBEAR_VERSION "2026.91"
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  530|       |		/* V_S, the server's version string (CR and NL excluded) */
  531|  2.06k|		buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
  532|       |
  533|       |		/* I_C, the payload of the client's SSH_MSG_KEXINIT */
  534|  2.06k|		buf_putstring(ses.kexhashbuf,
  535|  2.06k|			(const char*)ses.transkexinit->data, ses.transkexinit->len);
  536|       |		/* I_S, the payload of the server's SSH_MSG_KEXINIT */
  537|  2.06k|		buf_setpos(ses.payload, ses.payload_beginning);
  538|  2.06k|		buf_putstring(ses.kexhashbuf,
  539|  2.06k|			(const char*)buf_getptr(ses.payload, ses.payload->len-ses.payload->pos),
  540|  2.06k|			ses.payload->len-ses.payload->pos);
  541|  2.06k|		ses.requirenext = SSH_MSG_KEXDH_REPLY;
  ------------------
  |  |   39|  2.06k|#define SSH_MSG_KEXDH_REPLY            31
  ------------------
  542|  2.06k|	} else {
  543|       |		/* SERVER */
  544|       |
  545|       |		/* read the peer's choice of algos */
  546|      0|		read_kex_algos();
  547|       |		/* V_C, the client's version string (CR and NL excluded) */
  548|      0|		buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
  549|       |		/* V_S, the server's version string (CR and NL excluded) */
  550|      0|		buf_putstring(ses.kexhashbuf, LOCAL_IDENT, local_ident_len);
  ------------------
  |  |   14|      0|#define LOCAL_IDENT "SSH-2.0-dropbear" IDENT_VERSION_PART
  |  |  ------------------
  |  |  |  |   12|      0|#define IDENT_VERSION_PART "_" DROPBEAR_VERSION
  |  |  |  |  ------------------
  |  |  |  |  |  |    7|      0|#define DROPBEAR_VERSION "2026.91"
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  551|       |
  552|       |		/* I_C, the payload of the client's SSH_MSG_KEXINIT */
  553|      0|		buf_setpos(ses.payload, ses.payload_beginning);
  554|      0|		buf_putstring(ses.kexhashbuf, 
  555|      0|			(const char*)buf_getptr(ses.payload, ses.payload->len-ses.payload->pos),
  556|      0|			ses.payload->len-ses.payload->pos);
  557|       |
  558|       |		/* I_S, the payload of the server's SSH_MSG_KEXINIT */
  559|      0|		buf_putstring(ses.kexhashbuf,
  560|      0|			(const char*)ses.transkexinit->data, ses.transkexinit->len);
  561|       |
  562|      0|		ses.requirenext = SSH_MSG_KEXDH_INIT;
  ------------------
  |  |   38|      0|#define SSH_MSG_KEXDH_INIT             30
  ------------------
  563|      0|	}
  564|       |
  565|  2.06k|	buf_free(ses.transkexinit);
  566|  2.06k|	ses.transkexinit = NULL;
  567|       |	/* the rest of ses.kexhashbuf will be done after DH exchange */
  568|       |
  569|  2.06k|	ses.kexstate.recvkexinit = 1;
  570|       |
  571|  2.06k|	if (ses.kexstate.strict_kex && !ses.kexstate.donefirstkex && ses.recvseq != 1) {
  ------------------
  |  Branch (571:6): [True: 0, False: 2.06k]
  |  Branch (571:33): [True: 0, False: 0]
  |  Branch (571:63): [True: 0, False: 0]
  ------------------
  572|      0|		dropbear_exit("First packet wasn't kexinit");
  573|      0|	}
  574|       |
  575|  2.06k|	TRACE(("leave recv_msg_kexinit"))
  576|  2.06k|}
common-kex.c:switch_keys:
  120|  1.08k|static void switch_keys() {
  121|  1.08k|	TRACE2(("enter switch_keys"))
  122|  1.08k|	if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
  ------------------
  |  Branch (122:8): [True: 1.08k, False: 0]
  |  Branch (122:36): [True: 1.08k, False: 0]
  ------------------
  123|      0|		dropbear_exit("Unexpected newkeys message");
  124|      0|	}
  125|       |
  126|  1.08k|	if (!ses.keys) {
  ------------------
  |  Branch (126:6): [True: 0, False: 1.08k]
  ------------------
  127|      0|		ses.keys = m_malloc(sizeof(*ses.newkeys));
  128|      0|	}
  129|  1.08k|	if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
  ------------------
  |  Branch (129:6): [True: 1.08k, False: 0]
  |  Branch (129:34): [True: 0, False: 1.08k]
  ------------------
  130|      0|		TRACE(("switch_keys recv"))
  131|       |#ifndef DISABLE_ZLIB
  132|       |		gen_new_zstream_recv();
  133|       |#endif
  134|      0|		ses.keys->recv = ses.newkeys->recv;
  135|      0|		m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
  136|      0|		ses.newkeys->recv.valid = 0;
  137|      0|	}
  138|  1.08k|	if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
  ------------------
  |  Branch (138:6): [True: 0, False: 1.08k]
  |  Branch (138:34): [True: 0, False: 0]
  ------------------
  139|      0|		TRACE(("switch_keys trans"))
  140|       |#ifndef DISABLE_ZLIB
  141|       |		gen_new_zstream_trans();
  142|       |#endif
  143|      0|		ses.keys->trans = ses.newkeys->trans;
  144|      0|		m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
  145|      0|		ses.newkeys->trans.valid = 0;
  146|      0|	}
  147|  1.08k|	if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
  ------------------
  |  Branch (147:6): [True: 0, False: 1.08k]
  |  Branch (147:34): [True: 0, False: 0]
  ------------------
  148|      0|	{
  149|      0|		TRACE(("switch_keys done"))
  150|      0|		ses.keys->algo_kex = ses.newkeys->algo_kex;
  151|      0|		ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
  152|      0|		ses.keys->algo_signature = ses.newkeys->algo_signature;
  153|      0|		m_free(ses.newkeys);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  154|       |		ses.newkeys = NULL;
  155|      0|		kexinitialise();
  156|      0|	}
  157|  1.08k|	TRACE2(("leave switch_keys"))
  158|  1.08k|}
common-kex.c:kex_setup_compress:
  204|  2.70k|static void kex_setup_compress(void) {
  205|  2.70k|#ifdef DISABLE_ZLIB
  206|  2.70k|	ses.compress_algos_c2s = ssh_nocompress;
  207|  2.70k|	ses.compress_algos_s2c = ssh_nocompress;
  208|       |#else
  209|       |
  210|       |	if (!opts.compression) {
  211|       |		ses.compress_algos_c2s = ssh_nocompress;
  212|       |		ses.compress_algos_s2c = ssh_nocompress;
  213|       |		return;
  214|       |	}
  215|       |
  216|       |	if (IS_DROPBEAR_CLIENT) {
  217|       |		/* TODO: should c2s in dbclient be disabled?
  218|       |		 * Current Dropbear server disables it. Disabling it also
  219|       |		 * lets DROPBEAR_CLI_IMMEDIATE_AUTH work (see comment there) */
  220|       |		ses.compress_algos_c2s = ssh_compress;
  221|       |		ses.compress_algos_s2c = ssh_compress;
  222|       |	} else {
  223|       |		ses.compress_algos_c2s = ssh_nocompress;
  224|       |		ses.compress_algos_s2c = ssh_compress;
  225|       |	}
  226|       |#endif
  227|  2.70k|}
common-kex.c:kexinitialise:
  236|  2.70k|static void kexinitialise() {
  237|       |
  238|  2.70k|	TRACE(("kexinitialise()"))
  239|       |
  240|       |	/* sent/recv'd MSG_KEXINIT */
  241|  2.70k|	ses.kexstate.sentkexinit = 0;
  242|  2.70k|	ses.kexstate.recvkexinit = 0;
  243|       |
  244|       |	/* sent/recv'd MSG_NEWKEYS */
  245|  2.70k|	ses.kexstate.recvnewkeys = 0;
  246|  2.70k|	ses.kexstate.sentnewkeys = 0;
  247|       |
  248|       |	/* first_packet_follows */
  249|  2.70k|	ses.kexstate.them_firstfollows = 0;
  250|       |
  251|  2.70k|	ses.kexstate.datatrans = 0;
  252|  2.70k|	ses.kexstate.datarecv = 0;
  253|       |
  254|  2.70k|	ses.kexstate.our_first_follows_matches = 0;
  255|       |
  256|  2.70k|	ses.kexstate.lastkextime = monotonic_now();
  257|       |
  258|  2.70k|}
common-kex.c:read_kex_algos:
  611|  2.06k|static void read_kex_algos() {
  612|       |
  613|       |	/* for asymmetry */
  614|  2.06k|	algo_type * c2s_hash_algo = NULL;
  615|  2.06k|	algo_type * s2c_hash_algo = NULL;
  616|  2.06k|	algo_type * c2s_cipher_algo = NULL;
  617|  2.06k|	algo_type * s2c_cipher_algo = NULL;
  618|  2.06k|	algo_type * c2s_comp_algo = NULL;
  619|  2.06k|	algo_type * s2c_comp_algo = NULL;
  620|       |	/* the generic one */
  621|  2.06k|	algo_type * algo = NULL;
  622|       |
  623|       |	/* which algo couldn't match */
  624|  2.06k|	char * erralgo = NULL;
  625|       |
  626|  2.06k|	int goodguess = 0;
  627|  2.06k|	int allgood = 1; /* we AND this with each goodguess and see if its still
  628|       |						true after */
  629|  2.06k|	int kexguess2 = 0;
  630|       |
  631|  2.06k|	buf_incrpos(ses.payload, 16); /* start after the cookie */
  632|       |
  633|  2.06k|	memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
  634|       |
  635|       |	/* kex_algorithms */
  636|  2.06k|#if DROPBEAR_KEXGUESS2
  637|  2.06k|	if (buf_has_algo(ses.payload, KEXGUESS2_ALGO_NAME) == DROPBEAR_SUCCESS) {
  ------------------
  |  |  137|  2.06k|#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au"
  ------------------
              	if (buf_has_algo(ses.payload, KEXGUESS2_ALGO_NAME) == DROPBEAR_SUCCESS) {
  ------------------
  |  |  111|  2.06k|#define DROPBEAR_SUCCESS 0
  ------------------
  |  Branch (637:6): [True: 4, False: 2.05k]
  ------------------
  638|      4|		kexguess2 = 1;
  639|      4|	}
  640|  2.06k|#endif
  641|       |
  642|  2.06k|#if DROPBEAR_EXT_INFO
  643|       |	/* Determine if SSH_MSG_EXT_INFO messages should be sent.
  644|       |	Should be done for the first key exchange. Only required on server side
  645|       |    for server-sig-algs */
  646|  2.06k|	if (IS_DROPBEAR_SERVER) {
  ------------------
  |  |  381|  2.06k|#define IS_DROPBEAR_SERVER (ses.isserver == 1)
  |  |  ------------------
  |  |  |  Branch (381:28): [True: 0, False: 2.06k]
  |  |  ------------------
  ------------------
  647|      0|		if (!ses.kexstate.donefirstkex) {
  ------------------
  |  Branch (647:7): [True: 0, False: 0]
  ------------------
  648|      0|			if (buf_has_algo(ses.payload, SSH_EXT_INFO_C) == DROPBEAR_SUCCESS) {
  ------------------
  |  |  100|      0|#define SSH_EXT_INFO_C "ext-info-c"
  ------------------
              			if (buf_has_algo(ses.payload, SSH_EXT_INFO_C) == DROPBEAR_SUCCESS) {
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  |  Branch (648:8): [True: 0, False: 0]
  ------------------
  649|      0|				ses.allow_ext_info = 1;
  650|      0|			}
  651|      0|		}
  652|      0|	}
  653|  2.06k|#endif
  654|       |
  655|  2.06k|	if (!ses.kexstate.donefirstkex) {
  ------------------
  |  Branch (655:6): [True: 0, False: 2.06k]
  ------------------
  656|      0|		const char* strict_name;
  657|      0|		if (IS_DROPBEAR_CLIENT) {
  ------------------
  |  |  382|      0|#define IS_DROPBEAR_CLIENT (ses.isserver == 0)
  |  |  ------------------
  |  |  |  Branch (382:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  658|      0|			strict_name = SSH_STRICT_KEX_S;
  ------------------
  |  |  104|      0|#define SSH_STRICT_KEX_S "kex-strict-s-v00@openssh.com"
  ------------------
  659|      0|		} else {
  660|      0|			strict_name = SSH_STRICT_KEX_C;
  ------------------
  |  |  105|      0|#define SSH_STRICT_KEX_C "kex-strict-c-v00@openssh.com"
  ------------------
  661|      0|		}
  662|      0|		if (buf_has_algo(ses.payload, strict_name) == DROPBEAR_SUCCESS) {
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  |  Branch (662:7): [True: 0, False: 0]
  ------------------
  663|      0|			ses.kexstate.strict_kex = 1;
  664|      0|		}
  665|      0|	}
  666|       |
  667|  2.06k|	algo = buf_match_algo(ses.payload, sshkex, kexguess2, &goodguess);
  668|  2.06k|	allgood &= goodguess;
  669|  2.06k|	if (algo == NULL || algo->data == NULL) {
  ------------------
  |  Branch (669:6): [True: 257, False: 1.80k]
  |  Branch (669:22): [True: 2, False: 1.80k]
  ------------------
  670|       |		/* kexguess2, ext-info-c, ext-info-s should not match negotiation */
  671|    192|		erralgo = "kex";
  672|    192|		goto error;
  673|    192|	}
  674|  1.87k|	TRACE(("kexguess2 %d", kexguess2))
  675|  1.87k|	DEBUG3(("kex algo %s", algo->name))
  676|  1.87k|	ses.newkeys->algo_kex = algo->data;
  677|       |
  678|       |	/* server_host_key_algorithms */
  679|  1.87k|	algo = buf_match_algo(ses.payload, sigalgs, kexguess2, &goodguess);
  680|  1.87k|	allgood &= goodguess;
  681|  1.87k|	if (algo == NULL) {
  ------------------
  |  Branch (681:6): [True: 2, False: 1.86k]
  ------------------
  682|      2|		erralgo = "hostkey";
  683|      2|		goto error;
  684|      2|	}
  685|  1.86k|	DEBUG2(("hostkey algo %s", algo->name))
  686|  1.86k|	ses.newkeys->algo_signature = algo->val;
  687|  1.86k|	ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
  688|       |
  689|       |	/* encryption_algorithms_client_to_server */
  690|  1.86k|	c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
  691|  1.86k|	if (c2s_cipher_algo == NULL) {
  ------------------
  |  Branch (691:6): [True: 6, False: 1.86k]
  ------------------
  692|      6|		erralgo = "enc c->s";
  693|      6|		goto error;
  694|      6|	}
  695|  1.86k|	DEBUG2(("enc  c2s is %s", c2s_cipher_algo->name))
  696|       |
  697|       |	/* encryption_algorithms_server_to_client */
  698|  1.86k|	s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
  699|  1.86k|	if (s2c_cipher_algo == NULL) {
  ------------------
  |  Branch (699:6): [True: 3, False: 1.85k]
  ------------------
  700|      3|		erralgo = "enc s->c";
  701|      3|		goto error;
  702|      3|	}
  703|  1.85k|	DEBUG2(("enc  s2c is %s", s2c_cipher_algo->name))
  704|       |
  705|       |	/* mac_algorithms_client_to_server */
  706|  1.85k|	c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
  707|  1.85k|#if DROPBEAR_AEAD_MODE
  708|  1.85k|	if (((struct dropbear_cipher_mode*)c2s_cipher_algo->mode)->aead_crypt != NULL) {
  ------------------
  |  Branch (708:6): [True: 8, False: 1.85k]
  ------------------
  709|      8|		c2s_hash_algo = NULL;
  710|      8|	} else
  711|  1.85k|#endif
  712|  1.85k|	if (c2s_hash_algo == NULL) {
  ------------------
  |  Branch (712:6): [True: 2, False: 1.84k]
  ------------------
  713|      2|		erralgo = "mac c->s";
  714|      2|		goto error;
  715|      2|	}
  716|  1.85k|	DEBUG2(("hmac c2s is %s", c2s_hash_algo ? c2s_hash_algo->name : "<implicit>"))
  717|       |
  718|       |	/* mac_algorithms_server_to_client */
  719|  1.85k|	s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
  720|  1.85k|#if DROPBEAR_AEAD_MODE
  721|  1.85k|	if (((struct dropbear_cipher_mode*)s2c_cipher_algo->mode)->aead_crypt != NULL) {
  ------------------
  |  Branch (721:6): [True: 5, False: 1.85k]
  ------------------
  722|      5|		s2c_hash_algo = NULL;
  723|      5|	} else
  724|  1.85k|#endif
  725|  1.85k|	if (s2c_hash_algo == NULL) {
  ------------------
  |  Branch (725:6): [True: 4, False: 1.84k]
  ------------------
  726|      4|		erralgo = "mac s->c";
  727|      4|		goto error;
  728|      4|	}
  729|  1.85k|	DEBUG2(("hmac s2c is %s", s2c_hash_algo ? s2c_hash_algo->name : "<implicit>"))
  730|       |
  731|       |	/* compression_algorithms_client_to_server */
  732|  1.85k|	c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos_c2s, 0, NULL);
  733|  1.85k|	if (c2s_comp_algo == NULL) {
  ------------------
  |  Branch (733:6): [True: 3, False: 1.85k]
  ------------------
  734|      3|		erralgo = "comp c->s";
  735|      3|		goto error;
  736|      3|	}
  737|  1.85k|	DEBUG2(("comp c2s is %s", c2s_comp_algo->name))
  738|       |
  739|       |	/* compression_algorithms_server_to_client */
  740|  1.85k|	s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos_s2c, 0, NULL);
  741|  1.85k|	if (s2c_comp_algo == NULL) {
  ------------------
  |  Branch (741:6): [True: 1, False: 1.84k]
  ------------------
  742|      1|		erralgo = "comp s->c";
  743|      1|		goto error;
  744|      1|	}
  745|  1.84k|	DEBUG2(("comp s2c is %s", s2c_comp_algo->name))
  746|       |
  747|       |	/* languages_client_to_server */
  748|  1.84k|	buf_eatstring(ses.payload);
  749|       |
  750|       |	/* languages_server_to_client */
  751|  1.84k|	buf_eatstring(ses.payload);
  752|       |
  753|       |	/* their first_kex_packet_follows */
  754|  1.84k|	if (buf_getbool(ses.payload)) {
  ------------------
  |  Branch (754:6): [True: 36, False: 1.81k]
  ------------------
  755|     36|		TRACE(("them kex firstfollows. allgood %d", allgood))
  756|     36|		ses.kexstate.them_firstfollows = 1;
  757|       |		/* if the guess wasn't good, we ignore the packet sent */
  758|     36|		if (!allgood) {
  ------------------
  |  Branch (758:7): [True: 35, False: 1]
  ------------------
  759|     35|			ses.ignorenext = 1;
  760|     35|		}
  761|     36|	}
  762|       |
  763|       |	/* Handle the asymmetry */
  764|  1.84k|	if (IS_DROPBEAR_CLIENT) {
  ------------------
  |  |  382|  1.84k|#define IS_DROPBEAR_CLIENT (ses.isserver == 0)
  |  |  ------------------
  |  |  |  Branch (382:28): [True: 1.66k, False: 185]
  |  |  ------------------
  ------------------
  765|  1.66k|		ses.newkeys->recv.algo_crypt = 
  766|  1.66k|			(struct dropbear_cipher*)s2c_cipher_algo->data;
  767|  1.66k|		ses.newkeys->trans.algo_crypt = 
  768|  1.66k|			(struct dropbear_cipher*)c2s_cipher_algo->data;
  769|  1.66k|		ses.newkeys->recv.crypt_mode = 
  770|  1.66k|			(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
  771|  1.66k|		ses.newkeys->trans.crypt_mode =
  772|  1.66k|			(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
  773|  1.66k|		ses.newkeys->recv.algo_mac = 
  774|  1.66k|#if DROPBEAR_AEAD_MODE
  775|  1.66k|			s2c_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac :
  ------------------
  |  Branch (775:4): [True: 1, False: 1.66k]
  ------------------
  776|  1.66k|#endif
  777|  1.66k|			(struct dropbear_hash*)s2c_hash_algo->data;
  778|  1.66k|		ses.newkeys->trans.algo_mac = 
  779|  1.66k|#if DROPBEAR_AEAD_MODE
  780|  1.66k|			c2s_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac :
  ------------------
  |  Branch (780:4): [True: 1, False: 1.66k]
  ------------------
  781|  1.66k|#endif
  782|  1.66k|			(struct dropbear_hash*)c2s_hash_algo->data;
  783|  1.66k|		ses.newkeys->recv.algo_comp = s2c_comp_algo->val;
  784|  1.66k|		ses.newkeys->trans.algo_comp = c2s_comp_algo->val;
  785|  1.66k|	} else {
  786|       |		/* SERVER */
  787|    185|		ses.newkeys->recv.algo_crypt = 
  788|    185|			(struct dropbear_cipher*)c2s_cipher_algo->data;
  789|    185|		ses.newkeys->trans.algo_crypt = 
  790|    185|			(struct dropbear_cipher*)s2c_cipher_algo->data;
  791|    185|		ses.newkeys->recv.crypt_mode =
  792|    185|			(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
  793|    185|		ses.newkeys->trans.crypt_mode =
  794|    185|			(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
  795|    185|		ses.newkeys->recv.algo_mac = 
  796|    185|#if DROPBEAR_AEAD_MODE
  797|    185|			c2s_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac :
  ------------------
  |  Branch (797:4): [True: 0, False: 185]
  ------------------
  798|    185|#endif
  799|    185|			(struct dropbear_hash*)c2s_hash_algo->data;
  800|    185|		ses.newkeys->trans.algo_mac = 
  801|    185|#if DROPBEAR_AEAD_MODE
  802|    185|			s2c_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac :
  ------------------
  |  Branch (802:4): [True: 0, False: 185]
  ------------------
  803|    185|#endif
  804|    185|			(struct dropbear_hash*)s2c_hash_algo->data;
  805|    185|		ses.newkeys->recv.algo_comp = c2s_comp_algo->val;
  806|    185|		ses.newkeys->trans.algo_comp = s2c_comp_algo->val;
  807|    185|	}
  808|       |
  809|  1.84k|#if DROPBEAR_FUZZ
  810|  1.84k|	if (fuzz.fuzzing) {
  ------------------
  |  Branch (810:6): [True: 1.66k, False: 185]
  ------------------
  811|  1.66k|		fuzz_kex_fakealgos();
  812|  1.66k|	}
  813|  1.84k|#endif
  814|       |
  815|       |	/* reserved for future extensions */
  816|  1.84k|	buf_getint(ses.payload);
  817|       |
  818|  1.84k|	if (ses.send_kex_first_guess && allgood) {
  ------------------
  |  Branch (818:6): [True: 1.65k, False: 192]
  |  Branch (818:34): [True: 1, False: 1.65k]
  ------------------
  819|      1|		TRACE(("our_first_follows_matches 1"))
  820|      1|		ses.kexstate.our_first_follows_matches = 1;
  821|      1|	}
  822|  1.84k|	return;
  823|       |
  824|    213|error:
  825|    213|	dropbear_exit("No matching algo %s", erralgo);
  826|  1.85k|}

readhostkey:
   39|      1|	enum signkey_type *type) {
   40|       |
   41|      1|	int ret = DROPBEAR_FAILURE;
  ------------------
  |  |  112|      1|#define DROPBEAR_FAILURE -1
  ------------------
   42|      1|	buffer *buf;
   43|       |
   44|      1|	buf = buf_new(MAX_PRIVKEY_SIZE);
  ------------------
  |  |  262|      1|#define MAX_PRIVKEY_SIZE 1700
  ------------------
   45|       |
   46|      1|	if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      1|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (46:6): [True: 1, False: 0]
  ------------------
   47|      1|		goto out;
   48|      1|	}
   49|      0|	buf_setpos(buf, 0);
   50|       |
   51|      0|	addrandom(buf_getptr(buf, buf->len), buf->len);
   52|       |
   53|      0|	if (buf_get_priv_key(buf, hostkey, type) == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (53:6): [True: 0, False: 0]
  ------------------
   54|      0|		goto out;
   55|      0|	}
   56|       |
   57|      0|	ret = DROPBEAR_SUCCESS;
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
   58|      1|out:
   59|       |
   60|      1|	buf_burn_free(buf);
   61|      1|	return ret;
   62|      0|}
parse_ciphers_macs:
   66|      1|parse_ciphers_macs() {
   67|      1|	int printed_help = 0;
   68|      1|	if (opts.cipher_list) {
  ------------------
  |  Branch (68:6): [True: 0, False: 1]
  ------------------
   69|      0|		if (strcmp(opts.cipher_list, "help") == 0) {
  ------------------
  |  Branch (69:7): [True: 0, False: 0]
  ------------------
   70|      0|			char *ciphers = algolist_string(sshciphers);
   71|      0|			dropbear_log(LOG_INFO, "Available ciphers: %s", ciphers);
   72|      0|			m_free(ciphers);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
   73|      0|			printed_help = 1;
   74|      0|		} else {
   75|      0|			if (check_user_algos(opts.cipher_list, sshciphers, "cipher") == 0) {
  ------------------
  |  Branch (75:8): [True: 0, False: 0]
  ------------------
   76|      0|				dropbear_exit("No valid ciphers specified for '-c'");
   77|      0|			}
   78|      0|		}
   79|      0|	}
   80|       |
   81|      1|	if (opts.mac_list) {
  ------------------
  |  Branch (81:6): [True: 0, False: 1]
  ------------------
   82|      0|		if (strcmp(opts.mac_list, "help") == 0) {
  ------------------
  |  Branch (82:7): [True: 0, False: 0]
  ------------------
   83|      0|			char *macs = algolist_string(sshhashes);
   84|      0|			dropbear_log(LOG_INFO, "Available MACs: %s", macs);
   85|      0|			m_free(macs);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
   86|      0|			printed_help = 1;
   87|      0|		} else {
   88|      0|			if (check_user_algos(opts.mac_list, sshhashes, "MAC") == 0) {
  ------------------
  |  Branch (88:8): [True: 0, False: 0]
  ------------------
   89|      0|				dropbear_exit("No valid MACs specified for '-m'");
   90|      0|			}
   91|      0|		}
   92|      0|	}
   93|      1|	if (printed_help) {
  ------------------
  |  Branch (93:6): [True: 0, False: 1]
  ------------------
   94|      0|		dropbear_exit(".");
   95|      0|	}
   96|      1|}

common_session_init:
   47|  2.70k|void common_session_init(int sock_in, int sock_out) {
   48|  2.70k|	time_t now;
   49|       |
   50|       |#if DEBUG_TRACE
   51|       |	debug_start_net();
   52|       |#endif
   53|       |
   54|  2.70k|	TRACE(("enter session_init"))
   55|       |
   56|  2.70k|	ses.sock_in = sock_in;
   57|  2.70k|	ses.sock_out = sock_out;
   58|  2.70k|	ses.maxfd = MAX(sock_in, sock_out);
  ------------------
  |  Branch (58:14): [True: 0, False: 2.70k]
  ------------------
   59|       |
   60|  2.70k|	if (sock_in >= 0) {
  ------------------
  |  Branch (60:6): [True: 2.70k, False: 0]
  ------------------
   61|  2.70k|		setnonblocking(sock_in);
   62|  2.70k|	}
   63|  2.70k|	if (sock_out >= 0) {
  ------------------
  |  Branch (63:6): [True: 2.70k, False: 0]
  ------------------
   64|  2.70k|		setnonblocking(sock_out);
   65|  2.70k|	}
   66|       |
   67|  2.70k|	ses.socket_prio = DROPBEAR_PRIO_NORMAL;
   68|       |	/* Sets it to lowdelay */
   69|  2.70k|	update_channel_prio();
   70|       |
   71|       |#if !DROPBEAR_SVR_MULTIUSER
   72|       |	/* A sanity check to prevent an accidental configuration option
   73|       |	   leaving multiuser systems exposed */
   74|       |	{
   75|       |		int ret;
   76|       |		errno = 0;
   77|       |		ret = getgroups(0, NULL);
   78|       |		if (!(ret == -1 && errno == ENOSYS)) {
   79|       |			dropbear_exit("Non-multiuser Dropbear requires a non-multiuser kernel");
   80|       |		}
   81|       |	}
   82|       |#endif
   83|       |
   84|  2.70k|	now = monotonic_now();
   85|  2.70k|	ses.connect_time = now;
   86|  2.70k|	ses.last_packet_time_keepalive_recv = now;
   87|  2.70k|	ses.last_packet_time_idle = now;
   88|  2.70k|	ses.last_packet_time_any_sent = 0;
   89|  2.70k|	ses.last_packet_time_keepalive_sent = 0;
   90|       |	
   91|  2.70k|#if DROPBEAR_FUZZ
   92|  2.70k|	if (!fuzz.fuzzing)
  ------------------
  |  Branch (92:6): [True: 0, False: 2.70k]
  ------------------
   93|      0|#endif
   94|      0|	{
   95|      0|	if (pipe(ses.signal_pipe) < 0) {
  ------------------
  |  Branch (95:6): [True: 0, False: 0]
  ------------------
   96|      0|		dropbear_exit("Signal pipe failed");
   97|      0|	}
   98|      0|	setnonblocking(ses.signal_pipe[0]);
   99|      0|	setnonblocking(ses.signal_pipe[1]);
  100|      0|	ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
  ------------------
  |  Branch (100:14): [True: 0, False: 0]
  ------------------
  101|      0|	ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
  ------------------
  |  Branch (101:14): [True: 0, False: 0]
  ------------------
  102|      0|	}
  103|       |	
  104|  2.70k|	ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
  ------------------
  |  |  560|  2.70k|#define TRANS_MAX_PAYLOAD_LEN 16384
  ------------------
  105|  2.70k|	ses.transseq = 0;
  106|       |
  107|  2.70k|	ses.readbuf = NULL;
  108|  2.70k|	ses.payload = NULL;
  109|  2.70k|	ses.recvseq = 0;
  110|       |
  111|  2.70k|	initqueue(&ses.writequeue);
  112|       |
  113|  2.70k|	ses.requirenext = SSH_MSG_KEXINIT;
  ------------------
  |  |   36|  2.70k|#define SSH_MSG_KEXINIT                20
  ------------------
  114|  2.70k|	ses.dataallowed = 1; /* we can send data until we actually 
  115|       |							send the SSH_MSG_KEXINIT */
  116|  2.70k|	ses.ignorenext = 0;
  117|  2.70k|	ses.lastpacket = 0;
  118|  2.70k|	ses.reply_queue_head = NULL;
  119|  2.70k|	ses.reply_queue_tail = NULL;
  120|       |
  121|       |	/* set all the algos to none */
  122|  2.70k|	ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
  123|  2.70k|	ses.newkeys = NULL;
  124|  2.70k|	ses.keys->recv.algo_crypt = &dropbear_nocipher;
  125|  2.70k|	ses.keys->trans.algo_crypt = &dropbear_nocipher;
  126|  2.70k|	ses.keys->recv.crypt_mode = &dropbear_mode_none;
  127|  2.70k|	ses.keys->trans.crypt_mode = &dropbear_mode_none;
  128|       |	
  129|  2.70k|	ses.keys->recv.algo_mac = &dropbear_nohash;
  130|  2.70k|	ses.keys->trans.algo_mac = &dropbear_nohash;
  131|       |
  132|  2.70k|	ses.keys->algo_kex = NULL;
  133|  2.70k|	ses.keys->algo_hostkey = -1;
  134|  2.70k|	ses.keys->recv.algo_comp = DROPBEAR_COMP_NONE;
  135|  2.70k|	ses.keys->trans.algo_comp = DROPBEAR_COMP_NONE;
  136|       |
  137|       |#ifndef DISABLE_ZLIB
  138|       |	ses.keys->recv.zstream = NULL;
  139|       |	ses.keys->trans.zstream = NULL;
  140|       |#endif
  141|       |
  142|       |	/* key exchange buffers */
  143|  2.70k|	ses.session_id = NULL;
  144|  2.70k|	ses.kexhashbuf = NULL;
  145|  2.70k|	ses.transkexinit = NULL;
  146|  2.70k|	ses.dh_K = NULL;
  147|  2.70k|	ses.remoteident = NULL;
  148|       |
  149|  2.70k|	ses.chantypes = NULL;
  150|       |
  151|  2.70k|	ses.allowprivport = 0;
  152|       |
  153|       |#if DROPBEAR_PLUGIN
  154|       |        ses.plugin_session = NULL;
  155|       |#endif
  156|       |
  157|  2.70k|	TRACE(("leave session_init"))
  158|  2.70k|}
session_loop:
  160|  2.70k|void session_loop(void(*loophandler)(void)) {
  161|       |
  162|  2.70k|	fd_set readfd, writefd;
  163|  2.70k|	struct timeval timeout;
  164|  2.70k|	int val;
  165|       |
  166|       |	/* main loop, select()s for all sockets in use */
  167|   139k|	for(;;) {
  168|   139k|		const int writequeue_has_space = (ses.writequeue_len <= 2*TRANS_MAX_PAYLOAD_LEN);
  ------------------
  |  |  560|   139k|#define TRANS_MAX_PAYLOAD_LEN 16384
  ------------------
  169|       |
  170|   139k|		timeout.tv_sec = select_timeout();
  171|   139k|		timeout.tv_usec = 0;
  172|   139k|		DROPBEAR_FD_ZERO(&writefd);
  ------------------
  |  |  106|   139k|#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
  ------------------
  |  Branch (172:3): [Folded, False: 139k]
  ------------------
  173|   139k|		DROPBEAR_FD_ZERO(&readfd);
  ------------------
  |  |  106|   139k|#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
  ------------------
  |  Branch (173:3): [Folded, False: 139k]
  ------------------
  174|       |
  175|   139k|		dropbear_assert(ses.payload == NULL);
  ------------------
  |  |   84|   139k|#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
  |  |  ------------------
  |  |  |  Branch (84:37): [True: 0, False: 139k]
  |  |  |  Branch (84:93): [Folded, False: 139k]
  |  |  ------------------
  ------------------
  176|       |
  177|       |		/* We get woken up when signal handlers write to this pipe.
  178|       |		   SIGCHLD in svr-chansession is the only one currently. */
  179|   139k|#if DROPBEAR_FUZZ
  180|   139k|		if (!fuzz.fuzzing) 
  ------------------
  |  Branch (180:7): [True: 0, False: 139k]
  ------------------
  181|      0|#endif
  182|      0|		{
  183|      0|		FD_SET(ses.signal_pipe[0], &readfd);
  184|      0|		}
  185|       |
  186|       |		/* set up for channels which can be read/written */
  187|   139k|		setchannelfds(&readfd, &writefd, writequeue_has_space);
  188|       |
  189|       |		/* Pending connections to test */
  190|   139k|		set_connect_fds(&writefd);
  191|       |
  192|       |		/* We delay reading from the input socket during initial setup until
  193|       |		after we have written out our initial KEXINIT packet (empty writequeue). 
  194|       |		This means our initial packet can be in-flight while we're doing a blocking
  195|       |		read for the remote ident.
  196|       |		We also avoid reading from the socket if the writequeue is full, that avoids
  197|       |		replies backing up */
  198|   139k|		if (ses.sock_in != -1 
  ------------------
  |  Branch (198:7): [True: 139k, False: 0]
  ------------------
  199|   139k|			&& (ses.remoteident || isempty(&ses.writequeue)) 
  ------------------
  |  Branch (199:8): [True: 130k, False: 8.27k]
  |  Branch (199:27): [True: 2.86k, False: 5.40k]
  ------------------
  200|   133k|			&& writequeue_has_space) {
  ------------------
  |  Branch (200:7): [True: 133k, False: 0]
  ------------------
  201|   133k|			FD_SET(ses.sock_in, &readfd);
  202|   133k|		}
  203|       |
  204|       |		/* Ordering is important, this test must occur after any other function
  205|       |		might have queued packets (such as connection handlers) */
  206|   139k|		if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
  ------------------
  |  Branch (206:7): [True: 139k, False: 0]
  |  Branch (206:29): [True: 5.40k, False: 133k]
  ------------------
  207|  5.40k|			FD_SET(ses.sock_out, &writefd);
  208|  5.40k|		}
  209|       |
  210|   139k|		val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
  ------------------
  |  |   53|   139k|        wrapfd_select(nfds, readfds, writefds, exceptfds, timeout)
  ------------------
  211|       |
  212|   139k|		if (ses.exitflag) {
  ------------------
  |  Branch (212:7): [True: 0, False: 139k]
  ------------------
  213|      0|			dropbear_exit("Terminated by signal");
  214|      0|		}
  215|       |		
  216|   139k|		if (val < 0 && errno != EINTR) {
  ------------------
  |  Branch (216:7): [True: 155, False: 138k]
  |  Branch (216:18): [True: 0, False: 155]
  ------------------
  217|      0|			dropbear_exit("Error in select");
  218|      0|		}
  219|       |
  220|   139k|		if (val <= 0) {
  ------------------
  |  Branch (220:7): [True: 6.57k, False: 132k]
  ------------------
  221|       |			/* If we were interrupted or the select timed out, we still
  222|       |			 * want to iterate over channels etc for reading, to handle
  223|       |			 * server processes exiting etc. 
  224|       |			 * We don't want to read/write FDs. */
  225|  6.57k|			DROPBEAR_FD_ZERO(&writefd);
  ------------------
  |  |  106|  6.57k|#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
  ------------------
  |  Branch (225:4): [Folded, False: 6.57k]
  ------------------
  226|  6.57k|			DROPBEAR_FD_ZERO(&readfd);
  ------------------
  |  |  106|  6.57k|#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
  ------------------
  |  Branch (226:4): [Folded, False: 6.57k]
  ------------------
  227|  6.57k|		}
  228|       |		
  229|       |		/* We'll just empty out the pipe if required. We don't do
  230|       |		any thing with the data, since the pipe's purpose is purely to
  231|       |		wake up the select() above. */
  232|   139k|		ses.channel_signal_pending = 0;
  233|   139k|		if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
  ------------------
  |  Branch (233:7): [True: 0, False: 139k]
  ------------------
  234|      0|			char x;
  235|      0|			TRACE(("signal pipe set"))
  236|      0|			while (read(ses.signal_pipe[0], &x, 1) > 0) {}
  ------------------
  |  |   55|      0|#define read(fd, buf, count) wrapfd_read(fd, buf, count)
  ------------------
  |  Branch (236:11): [True: 0, False: 0]
  ------------------
  237|      0|			ses.channel_signal_pending = 1;
  238|      0|		}
  239|       |
  240|       |		/* check for auth timeout, rekeying required etc */
  241|   139k|		checktimeouts();
  242|       |
  243|       |		/* process session socket's incoming data */
  244|   139k|		if (ses.sock_in != -1) {
  ------------------
  |  Branch (244:7): [True: 139k, False: 0]
  ------------------
  245|   139k|			if (FD_ISSET(ses.sock_in, &readfd)) {
  ------------------
  |  Branch (245:8): [True: 127k, False: 11.8k]
  ------------------
  246|   127k|				if (!ses.remoteident) {
  ------------------
  |  Branch (246:9): [True: 2.70k, False: 124k]
  ------------------
  247|       |					/* blocking read of the version string */
  248|  2.70k|					read_session_identification();
  249|   124k|				} else {
  250|   124k|					read_packet();
  251|   124k|				}
  252|   127k|			}
  253|       |			
  254|       |			/* Process the decrypted packet. After this, the read buffer
  255|       |			 * will be ready for a new packet */
  256|   139k|			if (ses.payload != NULL) {
  ------------------
  |  Branch (256:8): [True: 31.9k, False: 107k]
  ------------------
  257|  31.9k|				process_packet();
  258|  31.9k|			}
  259|   139k|		}
  260|       |
  261|       |		/* if required, flush out any queued reply packets that
  262|       |		were being held up during a KEX */
  263|   139k|		maybe_flush_reply_queue();
  264|       |
  265|   139k|		handle_connect_fds(&writefd);
  266|       |
  267|       |		/* loop handler prior to channelio, in case the server loophandler closes
  268|       |		channels on process exit */
  269|   139k|		loophandler();
  270|       |
  271|       |		/* process pipes etc for the channels, ses.dataallowed == 0
  272|       |		 * during rekeying ) */
  273|   139k|		channelio(&readfd, &writefd);
  274|       |
  275|       |		/* process session socket's outgoing data */
  276|   139k|		if (ses.sock_out != -1) {
  ------------------
  |  Branch (276:7): [True: 136k, False: 2.70k]
  ------------------
  277|   136k|			if (!isempty(&ses.writequeue)) {
  ------------------
  |  Branch (277:8): [True: 23.8k, False: 112k]
  ------------------
  278|  23.8k|				write_packet();
  279|  23.8k|			}
  280|   136k|		}
  281|       |
  282|   139k|	} /* for(;;) */
  283|       |	
  284|       |	/* Not reached */
  285|  2.70k|}
session_cleanup:
  296|  2.70k|void session_cleanup() {
  297|       |	
  298|  2.70k|	TRACE(("enter session_cleanup"))
  299|       |	
  300|       |	/* we can't cleanup if we don't know the session state */
  301|  2.70k|	if (!ses.init_done) {
  ------------------
  |  Branch (301:6): [True: 0, False: 2.70k]
  ------------------
  302|      0|		TRACE(("leave session_cleanup: !ses.init_done"))
  303|      0|		return;
  304|      0|	}
  305|       |
  306|       |	/* BEWARE of changing order of functions here. */
  307|       |
  308|       |	/* Must be before extra_session_cleanup() */
  309|  2.70k|	chancleanup();
  310|       |
  311|  2.70k|	if (ses.extra_session_cleanup) {
  ------------------
  |  Branch (311:6): [True: 2.70k, False: 0]
  ------------------
  312|  2.70k|		ses.extra_session_cleanup();
  313|  2.70k|	}
  314|       |
  315|       |	/* After these are freed most functions will fail */
  316|  2.70k|#if DROPBEAR_CLEANUP
  317|       |	/* listeners call cleanup functions, this should occur before
  318|       |	other session state is freed. */
  319|  2.70k|	remove_all_listeners();
  320|       |
  321|  2.70k|	remove_connect_pending();
  322|       |
  323|  2.70k|	while (!isempty(&ses.writequeue)) {
  ------------------
  |  Branch (323:9): [True: 0, False: 2.70k]
  ------------------
  324|      0|		buf_free(dequeue(&ses.writequeue));
  325|      0|	}
  326|       |
  327|  2.70k|	m_free(ses.newkeys);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  328|       |#ifndef DISABLE_ZLIB
  329|       |	if (ses.keys->recv.zstream != NULL) {
  330|       |		if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
  331|       |			dropbear_exit("Crypto error");
  332|       |		}
  333|       |		m_free(ses.keys->recv.zstream);
  334|       |	}
  335|       |	if (ses.keys->trans.zstream != NULL) {
  336|       |		if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) {
  337|       |			dropbear_exit("Crypto error");
  338|       |		}
  339|       |		m_free(ses.keys->trans.zstream);
  340|       |	}
  341|       |#endif
  342|       |
  343|  2.70k|	m_free(ses.remoteident);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  344|  2.70k|	m_free(ses.authstate.pw_dir);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  345|  2.70k|	m_free(ses.authstate.pw_name);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  346|  2.70k|	m_free(ses.authstate.pw_shell);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  347|  2.70k|	m_free(ses.authstate.pw_passwd);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  348|  2.70k|	m_free(ses.authstate.username);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  349|  2.70k|#endif
  350|       |
  351|  2.70k|	cleanup_buf(&ses.session_id);
  352|  2.70k|	cleanup_buf(&ses.hash);
  353|  2.70k|	cleanup_buf(&ses.payload);
  354|  2.70k|	cleanup_buf(&ses.readbuf);
  355|  2.70k|	cleanup_buf(&ses.writepayload);
  356|  2.70k|	cleanup_buf(&ses.kexhashbuf);
  357|  2.70k|	cleanup_buf(&ses.transkexinit);
  358|  2.70k|	if (ses.dh_K) {
  ------------------
  |  Branch (358:6): [True: 0, False: 2.70k]
  ------------------
  359|      0|		mp_clear(ses.dh_K);
  360|      0|	}
  361|  2.70k|	m_free(ses.dh_K);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  362|  2.70k|	if (ses.dh_K_bytes) {
  ------------------
  |  Branch (362:6): [True: 0, False: 2.70k]
  ------------------
  363|      0|		buf_burn_free(ses.dh_K_bytes);
  364|      0|	}
  365|       |
  366|  2.70k|	m_burn(ses.keys, sizeof(struct key_context));
  367|  2.70k|	m_free(ses.keys);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  368|       |
  369|  2.70k|	TRACE(("leave session_cleanup"))
  370|  2.70k|}
send_session_identification:
  372|  2.70k|void send_session_identification() {
  373|  2.70k|	buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1);
  ------------------
  |  |   14|  2.70k|#define LOCAL_IDENT "SSH-2.0-dropbear" IDENT_VERSION_PART
  ------------------
  374|  2.70k|	buf_putbytes(writebuf, (const unsigned char *) LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
  ------------------
  |  |   14|  2.70k|#define LOCAL_IDENT "SSH-2.0-dropbear" IDENT_VERSION_PART
  ------------------
              	buf_putbytes(writebuf, (const unsigned char *) LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
  ------------------
  |  |   14|  2.70k|#define LOCAL_IDENT "SSH-2.0-dropbear" IDENT_VERSION_PART
  ------------------
  375|  2.70k|	writebuf_enqueue(writebuf);
  376|  2.70k|}
ignore_recv_response:
  501|    259|void ignore_recv_response() {
  502|       |	/* Do nothing */
  503|    259|	TRACE(("Ignored msg_request_response"))
  504|    259|}
update_channel_prio:
  699|  3.35k|void update_channel_prio() {
  700|  3.35k|	enum dropbear_prio new_prio;
  701|  3.35k|	int any = 0;
  702|  3.35k|	unsigned int i;
  703|       |
  704|  3.35k|	TRACE(("update_channel_prio"))
  705|       |
  706|  3.35k|	if (ses.sock_out < 0) {
  ------------------
  |  Branch (706:6): [True: 0, False: 3.35k]
  ------------------
  707|      0|		TRACE(("leave update_channel_prio: no socket"))
  708|      0|		return;
  709|      0|	}
  710|       |
  711|  3.35k|	new_prio = DROPBEAR_PRIO_NORMAL;
  712|  3.99k|	for (i = 0; i < ses.chansize; i++) {
  ------------------
  |  Branch (712:14): [True: 647, False: 3.35k]
  ------------------
  713|    647|		struct Channel *channel = ses.channels[i];
  714|    647|		if (!channel) {
  ------------------
  |  Branch (714:7): [True: 647, False: 0]
  ------------------
  715|    647|			continue;
  716|    647|		}
  717|      0|		any = 1;
  718|      0|		if (channel->prio == DROPBEAR_PRIO_LOWDELAY) {
  ------------------
  |  Branch (718:7): [True: 0, False: 0]
  ------------------
  719|      0|			new_prio = DROPBEAR_PRIO_LOWDELAY;
  720|      0|			break;
  721|      0|		}
  722|      0|	}
  723|       |
  724|  3.35k|	if (any == 0) {
  ------------------
  |  Branch (724:6): [True: 3.35k, False: 0]
  ------------------
  725|       |		/* lowdelay during setup */
  726|  3.35k|		TRACE(("update_channel_prio: not any"))
  727|  3.35k|		new_prio = DROPBEAR_PRIO_LOWDELAY;
  728|  3.35k|	}
  729|       |
  730|  3.35k|	if (new_prio != ses.socket_prio) {
  ------------------
  |  Branch (730:6): [True: 2.70k, False: 647]
  ------------------
  731|  2.70k|		TRACE(("Dropbear priority transitioning %d -> %d", ses.socket_prio, new_prio))
  732|  2.70k|		set_sock_priority(ses.sock_out, new_prio);
  733|  2.70k|		ses.socket_prio = new_prio;
  734|  2.70k|	}
  735|  3.35k|}
common-session.c:cleanup_buf:
  287|  18.9k|static void cleanup_buf(buffer **buf) {
  288|  18.9k|	if (!*buf) {
  ------------------
  |  Branch (288:6): [True: 10.6k, False: 8.30k]
  ------------------
  289|  10.6k|		return;
  290|  10.6k|	}
  291|  8.30k|	buf_burn_free(*buf);
  292|       |	*buf = NULL;
  293|  8.30k|}
common-session.c:read_session_identification:
  378|  2.70k|static void read_session_identification() {
  379|       |	/* max length of 255 chars */
  380|  2.70k|	char linebuf[256];
  381|  2.70k|	int len = 0;
  382|  2.70k|	char done = 0;
  383|  2.70k|	int i;
  384|       |
  385|       |	/* Servers may send other lines of data before sending the
  386|       |	 * version string, client must be able to process such lines.
  387|       |	 * If they send more than 50 lines, something is wrong */
  388|  5.88k|	for (i = IS_DROPBEAR_CLIENT ? 50 : 1; i > 0; i--) {
  ------------------
  |  |  382|  2.70k|#define IS_DROPBEAR_CLIENT (ses.isserver == 0)
  |  |  ------------------
  |  |  |  Branch (382:28): [True: 2.70k, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (388:40): [True: 5.82k, False: 57]
  ------------------
  389|  5.82k|		len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));
  390|       |
  391|  5.82k|		if (len < 0 && errno != EINTR) {
  ------------------
  |  Branch (391:7): [True: 2.89k, False: 2.93k]
  |  Branch (391:18): [True: 91, False: 2.80k]
  ------------------
  392|       |			/* It failed */
  393|     91|			break;
  394|     91|		}
  395|       |
  396|  5.73k|		if (len >= 4 && memcmp(linebuf, "SSH-", 4) == 0) {
  ------------------
  |  Branch (396:7): [True: 2.86k, False: 2.87k]
  |  Branch (396:19): [True: 2.55k, False: 307]
  ------------------
  397|       |			/* start of line matches */
  398|  2.55k|			done = 1;
  399|  2.55k|			break;
  400|  2.55k|		}
  401|  5.73k|	}
  402|       |
  403|  2.70k|	if (!done) {
  ------------------
  |  Branch (403:6): [True: 148, False: 2.55k]
  ------------------
  404|    148|		TRACE(("error reading remote ident: %s\n", strerror(errno)))
  405|    148|		ses.remoteclosed();
  406|  2.55k|	} else {
  407|       |		/* linebuf is already null terminated */
  408|  2.55k|		ses.remoteident = m_malloc(len);
  409|  2.55k|		memcpy(ses.remoteident, linebuf, len);
  410|  2.55k|	}
  411|       |
  412|       |	/* Shall assume that 2.x will be backwards compatible. */
  413|  2.70k|	if (strncmp(ses.remoteident, "SSH-2.", 6) != 0
  ------------------
  |  Branch (413:6): [True: 63, False: 2.64k]
  ------------------
  414|     63|			&& strncmp(ses.remoteident, "SSH-1.99-", 9) != 0) {
  ------------------
  |  Branch (414:7): [True: 60, False: 3]
  ------------------
  415|     60|		dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
  416|     60|	}
  417|       |
  418|  2.70k|	DEBUG1(("remoteident: %s", ses.remoteident))
  419|       |
  420|  2.70k|}
common-session.c:ident_readln:
  424|  5.82k|static int ident_readln(int fd, char* buf, int count) {
  425|       |	
  426|  5.82k|	char in;
  427|  5.82k|	int pos = 0;
  428|  5.82k|	int num = 0;
  429|  5.82k|	fd_set fds;
  430|  5.82k|	struct timeval timeout;
  431|       |
  432|  5.82k|	TRACE(("enter ident_readln"))
  433|       |
  434|  5.82k|	if (count < 1) {
  ------------------
  |  Branch (434:6): [True: 0, False: 5.82k]
  ------------------
  435|      0|		return -1;
  436|      0|	}
  437|       |
  438|  5.82k|	DROPBEAR_FD_ZERO(&fds);
  ------------------
  |  |  106|  5.82k|#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
  ------------------
  |  Branch (438:2): [Folded, False: 5.82k]
  ------------------
  439|       |
  440|       |	/* select since it's a non-blocking fd */
  441|       |	
  442|       |	/* leave space to null-terminate */
  443|  80.6k|	while (pos < count-1) {
  ------------------
  |  Branch (443:9): [True: 80.4k, False: 152]
  ------------------
  444|       |
  445|  80.4k|		FD_SET(fd, &fds);
  446|       |
  447|  80.4k|		timeout.tv_sec = 1;
  448|  80.4k|		timeout.tv_usec = 0;
  449|  80.4k|		if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
  ------------------
  |  |   53|  80.4k|        wrapfd_select(nfds, readfds, writefds, exceptfds, timeout)
  ------------------
  |  Branch (449:7): [True: 94, False: 80.3k]
  ------------------
  450|     94|			if (errno == EINTR) {
  ------------------
  |  Branch (450:8): [True: 94, False: 0]
  ------------------
  451|     94|				continue;
  452|     94|			}
  453|      0|			TRACE(("leave ident_readln: select error"))
  454|      0|			return -1;
  455|     94|		}
  456|       |
  457|  80.3k|		checktimeouts();
  458|       |		
  459|       |		/* Have to go one byte at a time, since we don't want to read past
  460|       |		 * the end, and have to somehow shove bytes back into the normal
  461|       |		 * packet reader */
  462|  80.3k|		if (FD_ISSET(fd, &fds)) {
  ------------------
  |  Branch (462:7): [True: 80.3k, False: 0]
  ------------------
  463|  80.3k|			num = read(fd, &in, 1);
  ------------------
  |  |   55|  80.3k|#define read(fd, buf, count) wrapfd_read(fd, buf, count)
  ------------------
  464|       |			/* a "\n" is a newline, "\r" we want to read in and keep going
  465|       |			 * so that it won't be read as part of the next line */
  466|  80.3k|			if (num < 0) {
  ------------------
  |  Branch (466:8): [True: 273, False: 80.1k]
  ------------------
  467|       |				/* error */
  468|    273|				if (errno == EINTR) {
  ------------------
  |  Branch (468:9): [True: 260, False: 13]
  ------------------
  469|    260|					continue; /* not a real error */
  470|    260|				}
  471|     13|				TRACE(("leave ident_readln: read error"))
  472|     13|				return -1;
  473|    273|			}
  474|  80.1k|			if (num == 0) {
  ------------------
  |  Branch (474:8): [True: 2.88k, False: 77.2k]
  ------------------
  475|       |				/* EOF */
  476|  2.88k|				TRACE(("leave ident_readln: EOF"))
  477|  2.88k|				return -1;
  478|  2.88k|			}
  479|       |
  480|  77.2k|#if DROPBEAR_FUZZ
  481|  77.2k|			fuzz_dump(&in, 1);
  482|  77.2k|#endif
  483|       |
  484|  77.2k|			if (in == '\n') {
  ------------------
  |  Branch (484:8): [True: 2.78k, False: 74.4k]
  ------------------
  485|       |				/* end of ident string */
  486|  2.78k|				break;
  487|  2.78k|			}
  488|       |			/* we don't want to include '\r's */
  489|  74.4k|			if (in != '\r') {
  ------------------
  |  Branch (489:8): [True: 72.7k, False: 1.73k]
  ------------------
  490|  72.7k|				buf[pos] = in;
  491|  72.7k|				pos++;
  492|  72.7k|			}
  493|  74.4k|		}
  494|  80.3k|	}
  495|       |
  496|  2.93k|	buf[pos] = '\0';
  497|  2.93k|	TRACE(("leave ident_readln: return %d", pos+1))
  498|  2.93k|	return pos+1;
  499|  5.82k|}
common-session.c:checktimeouts:
  545|   219k|static void checktimeouts() {
  546|       |
  547|   219k|	time_t now;
  548|   219k|	now = monotonic_now();
  549|       |
  550|   219k|	if (IS_DROPBEAR_SERVER && ses.authstate.authdone != 1
  ------------------
  |  |  381|   438k|#define IS_DROPBEAR_SERVER (ses.isserver == 1)
  |  |  ------------------
  |  |  |  Branch (381:28): [True: 0, False: 219k]
  |  |  ------------------
  ------------------
  |  Branch (550:28): [True: 0, False: 0]
  ------------------
  551|      0|		&& elapsed(now, ses.connect_time) >= AUTH_TIMEOUT) {
  ------------------
  |  |   35|      0|#define AUTH_TIMEOUT 300 /* we choose 5 minutes */
  ------------------
  |  Branch (551:6): [True: 0, False: 0]
  ------------------
  552|      0|			dropbear_close("Timeout before auth");
  553|      0|	}
  554|       |
  555|       |	/* we can't rekey if we haven't done remote ident exchange yet */
  556|   219k|	if (ses.remoteident == NULL) {
  ------------------
  |  Branch (556:6): [True: 88.6k, False: 130k]
  ------------------
  557|  88.6k|		return;
  558|  88.6k|	}
  559|       |
  560|   130k|	if (!ses.kexstate.sentkexinit
  ------------------
  |  Branch (560:6): [True: 0, False: 130k]
  ------------------
  561|      0|			&& (elapsed(now, ses.kexstate.lastkextime) >= KEX_REKEY_TIMEOUT
  ------------------
  |  |   28|      0|#define KEX_REKEY_TIMEOUT (3600 * 8)
  ------------------
  |  Branch (561:8): [True: 0, False: 0]
  ------------------
  562|      0|			|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA
  ------------------
  |  |   31|      0|#define KEX_REKEY_DATA (1<<30) /* 2^30 == 1GB, this value must be < INT_MAX */
  ------------------
  |  Branch (562:7): [True: 0, False: 0]
  ------------------
  563|      0|			|| ses.kexstate.needrekey)) {
  ------------------
  |  Branch (563:7): [True: 0, False: 0]
  ------------------
  564|      0|		TRACE(("rekeying after timeout or max data reached"))
  565|      0|		ses.kexstate.needrekey = 0;
  566|      0|		send_msg_kexinit();
  567|      0|	}
  568|       |
  569|   130k|	if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
  ------------------
  |  Branch (569:6): [True: 0, False: 130k]
  |  Branch (569:33): [True: 0, False: 0]
  ------------------
  570|       |		/* Avoid sending keepalives prior to auth - those are
  571|       |		not valid pre-auth packet types */
  572|       |
  573|       |		/* Send keepalives if we've been idle */
  574|      0|		if (elapsed(now, ses.last_packet_time_any_sent) >= opts.keepalive_secs) {
  ------------------
  |  Branch (574:7): [True: 0, False: 0]
  ------------------
  575|      0|			send_msg_keepalive();
  576|      0|		}
  577|       |
  578|       |		/* Also send an explicit keepalive message to trigger a response
  579|       |		if the remote end hasn't sent us anything */
  580|      0|		if (elapsed(now, ses.last_packet_time_keepalive_recv) >= opts.keepalive_secs
  ------------------
  |  Branch (580:7): [True: 0, False: 0]
  ------------------
  581|      0|			&& elapsed(now, ses.last_packet_time_keepalive_sent) >= opts.keepalive_secs) {
  ------------------
  |  Branch (581:7): [True: 0, False: 0]
  ------------------
  582|      0|			send_msg_keepalive();
  583|      0|		}
  584|       |
  585|      0|		if (elapsed(now, ses.last_packet_time_keepalive_recv)
  ------------------
  |  Branch (585:7): [True: 0, False: 0]
  ------------------
  586|      0|			>= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
  ------------------
  |  |  573|      0|#define DEFAULT_KEEPALIVE_LIMIT 3
  ------------------
  587|      0|			dropbear_exit("Keepalive timeout");
  588|      0|		}
  589|      0|	}
  590|       |
  591|   130k|	if (opts.idle_timeout_secs > 0
  ------------------
  |  Branch (591:6): [True: 0, False: 130k]
  ------------------
  592|      0|			&& elapsed(now, ses.last_packet_time_idle) >= opts.idle_timeout_secs) {
  ------------------
  |  Branch (592:7): [True: 0, False: 0]
  ------------------
  593|      0|		dropbear_close("Idle timeout");
  594|      0|	}
  595|       |
  596|   130k|	if (opts.max_duration_secs > 0
  ------------------
  |  Branch (596:6): [True: 0, False: 130k]
  ------------------
  597|      0|			&& elapsed(now, ses.connect_time) >= opts.max_duration_secs) {
  ------------------
  |  Branch (597:7): [True: 0, False: 0]
  ------------------
  598|      0|		dropbear_close("Max duration reached");
  599|      0|	}
  600|   130k|}
common-session.c:select_timeout:
  613|   139k|static long select_timeout() {
  614|       |	/* determine the minimum timeout that might be required, so
  615|       |	as to avoid waking when unneccessary */
  616|   139k|	long timeout = KEX_REKEY_TIMEOUT;
  ------------------
  |  |   28|   139k|#define KEX_REKEY_TIMEOUT (3600 * 8)
  ------------------
  617|   139k|	time_t now = monotonic_now();
  618|       |
  619|   139k|	if (!ses.kexstate.sentkexinit) {
  ------------------
  |  Branch (619:6): [True: 0, False: 139k]
  ------------------
  620|      0|		update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
  ------------------
  |  |   28|      0|#define KEX_REKEY_TIMEOUT (3600 * 8)
  ------------------
  621|      0|	}
  622|   139k|	if (ses.kexstate.needrekey) {
  ------------------
  |  Branch (622:6): [True: 0, False: 139k]
  ------------------
  623|      0|		timeout = 0;
  624|      0|	}
  625|       |
  626|   139k|	if (ses.authstate.authdone != 1 && IS_DROPBEAR_SERVER) {
  ------------------
  |  |  381|   115k|#define IS_DROPBEAR_SERVER (ses.isserver == 1)
  |  |  ------------------
  |  |  |  Branch (381:28): [True: 0, False: 115k]
  |  |  ------------------
  ------------------
  |  Branch (626:6): [True: 115k, False: 23.3k]
  ------------------
  627|       |		/* AUTH_TIMEOUT is only relevant before authdone */
  628|      0|		update_timeout(AUTH_TIMEOUT, now, ses.connect_time, &timeout);
  ------------------
  |  |   35|      0|#define AUTH_TIMEOUT 300 /* we choose 5 minutes */
  ------------------
  629|      0|	}
  630|       |
  631|   139k|	if (ses.authstate.authdone) {
  ------------------
  |  Branch (631:6): [True: 23.3k, False: 115k]
  ------------------
  632|  23.3k|		update_timeout(opts.keepalive_secs, now,
  633|  23.3k|			MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent),
  ------------------
  |  Branch (633:4): [True: 23.3k, False: 0]
  ------------------
  634|  23.3k|			&timeout);
  635|  23.3k|	}
  636|       |
  637|   139k|	update_timeout(opts.idle_timeout_secs, now, ses.last_packet_time_idle,
  638|   139k|		&timeout);
  639|       |
  640|   139k|	update_timeout(opts.max_duration_secs, now, ses.connect_time,
  641|   139k|		&timeout);
  642|       |
  643|       |	/* clamp negative timeouts to zero - event has already triggered */
  644|       |	return MAX(timeout, 0);
  ------------------
  |  Branch (644:9): [True: 139k, False: 0]
  ------------------
  645|   139k|}
common-session.c:update_timeout:
  602|   301k|static void update_timeout(long limit, time_t now, time_t last_event, long * timeout) {
  603|   301k|	TRACE2(("update_timeout limit %ld, now %llu, last %llu, timeout %ld",
  604|   301k|		limit,
  605|   301k|		(unsigned long long)now,
  606|   301k|		(unsigned long long)last_event, *timeout))
  607|   301k|	if (last_event > 0 && limit > 0) {
  ------------------
  |  Branch (607:6): [True: 301k, False: 0]
  |  Branch (607:24): [True: 0, False: 301k]
  ------------------
  608|       |		*timeout = MIN(*timeout, MAX(0, limit - elapsed(now, last_event)));
  ------------------
  |  Branch (608:14): [True: 0, False: 0]
  |  Branch (608:14): [True: 0, False: 0]
  |  Branch (608:14): [True: 0, False: 0]
  ------------------
  609|      0|		TRACE2(("new timeout %ld", *timeout))
  610|      0|	}
  611|   301k|}

strlcat:
  128|      2|{
  129|      2|	char *d = dst;
  130|      2|	const char *s = src;
  131|      2|	size_t n = siz;
  132|      2|	size_t dlen;
  133|       |
  134|       |	/* Find the end of dst and adjust bytes left but don't go past end */
  135|      8|	while (n-- != 0 && *d != '\0')
  ------------------
  |  Branch (135:9): [True: 8, False: 0]
  |  Branch (135:21): [True: 6, False: 2]
  ------------------
  136|      6|		d++;
  137|      2|	dlen = d - dst;
  138|      2|	n = siz - dlen;
  139|       |
  140|      2|	if (n == 0)
  ------------------
  |  Branch (140:6): [True: 0, False: 2]
  ------------------
  141|      0|		return(dlen + strlen(s));
  142|      9|	while (*s != '\0') {
  ------------------
  |  Branch (142:9): [True: 7, False: 2]
  ------------------
  143|      7|		if (n != 1) {
  ------------------
  |  Branch (143:7): [True: 6, False: 1]
  ------------------
  144|      6|			*d++ = *s;
  145|      6|			n--;
  146|      6|		}
  147|      7|		s++;
  148|      7|	}
  149|      2|	*d = '\0';
  150|       |
  151|      2|	return(dlen + (s - src));	/* count does not include NUL */
  152|      2|}

crypto_init:
   21|      1|void crypto_init() {
   22|       |
   23|      1|	const struct ltc_cipher_descriptor *regciphers[] = {
   24|      1|#if DROPBEAR_AES
   25|      1|		&aes_desc,
   26|      1|#endif
   27|       |#if DROPBEAR_3DES
   28|       |		&des3_desc,
   29|       |#endif
   30|      1|		NULL
   31|      1|	};
   32|       |
   33|      1|	const struct ltc_hash_descriptor *reghashes[] = {
   34|       |#if DROPBEAR_SHA1_HMAC
   35|       |		&sha1_desc,
   36|       |#endif
   37|      1|#if DROPBEAR_SHA256
   38|      1|		&sha256_desc,
   39|      1|#endif
   40|      1|#if DROPBEAR_SHA384
   41|      1|		&sha384_desc,
   42|      1|#endif
   43|      1|#if DROPBEAR_SHA512
   44|      1|		&sha512_desc,
   45|      1|#endif
   46|      1|		NULL
   47|      1|	};
   48|      1|	int i;
   49|       |
   50|      2|	for (i = 0; regciphers[i] != NULL; i++) {
  ------------------
  |  Branch (50:14): [True: 1, False: 1]
  ------------------
   51|      1|		if (register_cipher(regciphers[i]) == -1) {
  ------------------
  |  Branch (51:7): [True: 0, False: 1]
  ------------------
   52|      0|			dropbear_exit("Error registering crypto");
   53|      0|		}
   54|      1|	}
   55|       |
   56|      4|	for (i = 0; reghashes[i] != NULL; i++) {
  ------------------
  |  Branch (56:14): [True: 3, False: 1]
  ------------------
   57|      3|		if (register_hash(reghashes[i]) == -1) {
  ------------------
  |  Branch (57:7): [True: 0, False: 3]
  ------------------
   58|      0|			dropbear_exit("Error registering crypto");
   59|      0|		}
   60|      3|	}
   61|       |
   62|      1|#if DROPBEAR_LTC_PRNG
   63|      1|	dropbear_ltc_prng = register_prng(&dropbear_prng_desc);
   64|      1|	if (dropbear_ltc_prng == -1) {
  ------------------
  |  Branch (64:6): [True: 0, False: 1]
  ------------------
   65|      0|		dropbear_exit("Error registering crypto");
   66|      0|	}
   67|      1|#endif
   68|       |
   69|      1|	mp_rand_source(dropbear_rand_source);
   70|       |
   71|      1|#if DROPBEAR_ECC
   72|      1|	ltc_mp = ltm_desc;
   73|      1|	dropbear_ecc_fill_dp();
   74|      1|#endif
   75|      1|}

m_burn:
    5|  37.5k|void m_burn(void *data, unsigned int len) {
    6|       |
    7|       |#if defined(HAVE_MEMSET_S)
    8|       |	memset_s(data, len, 0x0, len);
    9|       |#elif defined(HAVE_EXPLICIT_BZERO)
   10|       |	explicit_bzero(data, len);
   11|       |#else
   12|       |	/* This must be volatile to avoid compiler optimisation */
   13|       |	volatile void *p = data;
   14|       |	memset((void*)p, 0x0, len);
   15|       |#endif
   16|  37.5k|}

m_strdup:
   12|      6|void * m_strdup(const char * str) {
   13|      6|    char* ret;
   14|      6|    unsigned int len;
   15|      6|    len = strlen(str);
   16|       |
   17|      6|    ret = m_malloc(len+1);
   18|      6|    if (ret == NULL) {
  ------------------
  |  Branch (18:9): [True: 0, False: 6]
  ------------------
   19|      0|        dropbear_exit("m_strdup failed");
   20|      0|    }
   21|      6|    memcpy(ret, str, len+1);
   22|      6|    return ret;
   23|      6|}
m_malloc_set_epoch:
   76|  2.70k|void m_malloc_set_epoch(unsigned int epoch) {
   77|  2.70k|    current_epoch = epoch;
   78|  2.70k|}
m_malloc_free_epoch:
   80|  2.70k|void m_malloc_free_epoch(unsigned int epoch, int dofree) {
   81|  2.70k|    struct dbmalloc_header* header;
   82|  2.70k|    struct dbmalloc_header* nextheader = NULL;
   83|  2.70k|    struct dbmalloc_header* oldstaple = staple;
   84|  2.70k|    staple = NULL;
   85|       |    /* free allocations from this epoch, create a new staple-anchored list from
   86|       |    the remainder */
   87|  2.74M|    for (header = oldstaple; header; header = nextheader)
  ------------------
  |  Branch (87:30): [True: 2.74M, False: 2.70k]
  ------------------
   88|  2.74M|    {
   89|  2.74M|        nextheader = header->next;
   90|  2.74M|        if (header->epoch == epoch) {
  ------------------
  |  Branch (90:13): [True: 7.22k, False: 2.73M]
  ------------------
   91|  7.22k|            if (dofree) {
  ------------------
  |  Branch (91:17): [True: 7.22k, False: 0]
  ------------------
   92|  7.22k|                free(header);
   93|  7.22k|            }
   94|  2.73M|        } else {
   95|  2.73M|            header->prev = NULL;
   96|       |            header->next = NULL;
   97|  2.73M|            put_alloc(header);
   98|  2.73M|        }
   99|  2.74M|    }
  100|  2.70k|}
m_malloc:
  131|   134k|void * m_malloc(size_t size) {
  132|   134k|    char* mem = NULL;
  133|   134k|    struct dbmalloc_header* header = NULL;
  134|       |
  135|   134k|    if (size == 0 || size > 1e9) {
  ------------------
  |  Branch (135:9): [True: 0, False: 134k]
  |  Branch (135:22): [True: 0, False: 134k]
  ------------------
  136|      0|        dropbear_exit("m_malloc failed");
  137|      0|    }
  138|       |
  139|   134k|    size = size + sizeof(struct dbmalloc_header);
  140|       |
  141|   134k|    mem = calloc(1, size);
  142|   134k|    if (mem == NULL) {
  ------------------
  |  Branch (142:9): [True: 0, False: 134k]
  ------------------
  143|      0|        dropbear_exit("m_malloc failed");
  144|      0|    }
  145|   134k|    header = (struct dbmalloc_header*)mem;
  146|   134k|    put_alloc(header);
  147|   134k|    header->epoch = current_epoch;
  148|   134k|    return &mem[sizeof(struct dbmalloc_header)];
  149|   134k|}
m_realloc:
  151|  2.69k|void * m_realloc(void* ptr, size_t size) {
  152|  2.69k|    char* mem = NULL;
  153|  2.69k|    struct dbmalloc_header* header = NULL;
  154|  2.69k|    if (size == 0 || size > 1e9) {
  ------------------
  |  Branch (154:9): [True: 0, False: 2.69k]
  |  Branch (154:22): [True: 0, False: 2.69k]
  ------------------
  155|      0|        dropbear_exit("m_realloc failed");
  156|      0|    }
  157|       |
  158|  2.69k|    header = get_header(ptr);
  159|  2.69k|    remove_alloc(header);
  160|       |
  161|  2.69k|    size = size + sizeof(struct dbmalloc_header);
  162|  2.69k|    mem = realloc(header, size);
  163|  2.69k|    if (mem == NULL) {
  ------------------
  |  Branch (163:9): [True: 0, False: 2.69k]
  ------------------
  164|      0|        dropbear_exit("m_realloc failed");
  165|      0|    }
  166|       |
  167|  2.69k|    header = (struct dbmalloc_header*)mem;
  168|  2.69k|    put_alloc(header);
  169|  2.69k|    return &mem[sizeof(struct dbmalloc_header)];
  170|  2.69k|}
m_free_direct:
  172|   142k|void m_free_direct(void* ptr) {
  173|   142k|    struct dbmalloc_header* header = NULL;
  174|   142k|    if (!ptr) {
  ------------------
  |  Branch (174:9): [True: 16.3k, False: 125k]
  ------------------
  175|  16.3k|        return;
  176|  16.3k|    }
  177|   125k|    header = get_header(ptr);
  178|   125k|    remove_alloc(header);
  179|   125k|    free(header);
  180|   125k|}
dbmalloc.c:put_alloc:
  102|  2.87M|static void put_alloc(struct dbmalloc_header *header) {
  103|  2.87M|    assert(header->next == NULL);
  ------------------
  |  Branch (103:5): [True: 0, False: 2.87M]
  |  Branch (103:5): [True: 2.87M, False: 0]
  ------------------
  104|  2.87M|    assert(header->prev == NULL);
  ------------------
  |  Branch (104:5): [True: 0, False: 2.87M]
  |  Branch (104:5): [True: 2.87M, False: 0]
  ------------------
  105|  2.87M|    if (staple) {
  ------------------
  |  Branch (105:9): [True: 2.87M, False: 2.70k]
  ------------------
  106|  2.87M|        staple->prev = header;
  107|  2.87M|    }
  108|  2.87M|    header->next = staple;
  109|  2.87M|    staple = header;
  110|  2.87M|}
dbmalloc.c:get_header:
  126|   128k|static struct dbmalloc_header* get_header(void* ptr) {
  127|   128k|    char* bptr = ptr;
  128|   128k|    return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)];
  129|   128k|}
dbmalloc.c:remove_alloc:
  112|   128k|static void remove_alloc(struct dbmalloc_header *header) {
  113|   128k|    if (header->prev) {
  ------------------
  |  Branch (113:9): [True: 53.1k, False: 75.2k]
  ------------------
  114|  53.1k|        header->prev->next = header->next;
  115|  53.1k|    }
  116|   128k|    if (header->next) {
  ------------------
  |  Branch (116:9): [True: 128k, False: 0]
  ------------------
  117|   128k|        header->next->prev = header->prev;
  118|   128k|    }
  119|   128k|    if (staple == header) {
  ------------------
  |  Branch (119:9): [True: 75.2k, False: 53.1k]
  ------------------
  120|  75.2k|        staple = header->next;
  121|  75.2k|    }
  122|   128k|    header->prev = NULL;
  123|       |    header->next = NULL;
  124|   128k|}

fuzz_seed:
  153|  2.70k|void fuzz_seed(const unsigned char* dat, unsigned int len) {
  154|  2.70k|	hash_state hs;
  155|  2.70k|	sha256_init(&hs);
  156|  2.70k|	sha256_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
  157|  2.70k|	sha256_process(&hs, dat, len);
  158|  2.70k|	sha256_done(&hs, hashpool);
  159|  2.70k|	counter = 0;
  160|  2.70k|	donerandinit = 1;
  161|  2.70k|}
genrandom:
  313|  26.5k|void genrandom(unsigned char* buf, unsigned int len) {
  314|       |
  315|  26.5k|	hash_state hs;
  316|  26.5k|	unsigned char hash[SHA256_HASH_SIZE];
  317|  26.5k|	unsigned int copylen;
  318|       |
  319|  26.5k|	if (!donerandinit) {
  ------------------
  |  Branch (319:6): [True: 0, False: 26.5k]
  ------------------
  320|      0|		dropbear_exit("seedrandom not done");
  321|      0|	}
  322|       |
  323|  53.0k|	while (len > 0) {
  ------------------
  |  Branch (323:9): [True: 26.5k, False: 26.5k]
  ------------------
  324|  26.5k|		sha256_init(&hs);
  325|  26.5k|		sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
  326|  26.5k|		sha256_process(&hs, (void*)&counter, sizeof(counter));
  327|  26.5k|		sha256_done(&hs, hash);
  328|       |
  329|  26.5k|		counter++;
  330|  26.5k|		if (counter > MAX_COUNTER) {
  ------------------
  |  |   35|  26.5k|#define MAX_COUNTER (1<<30)
  ------------------
  |  Branch (330:7): [True: 0, False: 26.5k]
  ------------------
  331|      0|			seedrandom();
  332|      0|		}
  333|       |
  334|       |		copylen = MIN(len, SHA256_HASH_SIZE);
  ------------------
  |  Branch (334:13): [True: 26.5k, False: 0]
  ------------------
  335|  26.5k|		memcpy(buf, hash, copylen);
  336|  26.5k|		len -= copylen;
  337|  26.5k|		buf += copylen;
  338|  26.5k|	}
  339|  26.5k|	m_burn(hash, sizeof(hash));
  340|  26.5k|}

dropbear_close:
   95|      3|void dropbear_close(const char* format, ...) {
   96|       |
   97|      3|	va_list param;
   98|       |
   99|      3|	va_start(param, format);
  100|      3|	_dropbear_exit(EXIT_SUCCESS, format, param);
  101|      3|	va_end(param);
  102|       |
  103|      0|}
dropbear_exit:
  105|  2.70k|void dropbear_exit(const char* format, ...) {
  106|       |
  107|  2.70k|	va_list param;
  108|       |
  109|  2.70k|	va_start(param, format);
  110|  2.70k|	_dropbear_exit(EXIT_FAILURE, format, param);
  111|  2.70k|	va_end(param);
  112|      0|}
dropbear_log:
  148|    697|void dropbear_log(int priority, const char* format, ...) {
  149|       |
  150|    697|	va_list param;
  151|       |
  152|    697|	va_start(param, format);
  153|    697|	_dropbear_log(priority, format, param);
  154|       |	va_end(param);
  155|    697|}
buf_readfile:
  489|      1|int buf_readfile(buffer* buf, const char* filename) {
  490|       |
  491|      1|	int fd = -1;
  492|      1|	int len;
  493|      1|	int maxlen;
  494|      1|	int ret = DROPBEAR_FAILURE;
  ------------------
  |  |  112|      1|#define DROPBEAR_FAILURE -1
  ------------------
  495|       |
  496|      1|	fd = open(filename, O_RDONLY);
  497|       |
  498|      1|	if (fd < 0) {
  ------------------
  |  Branch (498:6): [True: 1, False: 0]
  ------------------
  499|      1|		goto out;
  500|      1|	}
  501|       |	
  502|      0|	do {
  503|      0|		maxlen = buf->size - buf->pos;
  504|      0|		len = read(fd, buf_getwriteptr(buf, maxlen), maxlen);
  ------------------
  |  |   55|      0|#define read(fd, buf, count) wrapfd_read(fd, buf, count)
  ------------------
  505|      0|		if (len < 0) {
  ------------------
  |  Branch (505:7): [True: 0, False: 0]
  ------------------
  506|      0|			if (errno == EINTR || errno == EAGAIN) {
  ------------------
  |  Branch (506:8): [True: 0, False: 0]
  |  Branch (506:26): [True: 0, False: 0]
  ------------------
  507|      0|				continue;
  508|      0|			}
  509|      0|			goto out;
  510|      0|		}
  511|      0|		buf_incrwritepos(buf, len);
  512|      0|	} while (len < maxlen && len > 0);
  ------------------
  |  Branch (512:11): [True: 0, False: 0]
  |  Branch (512:27): [True: 0, False: 0]
  ------------------
  513|       |
  514|      0|	ret = DROPBEAR_SUCCESS;
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  515|       |
  516|      1|out:
  517|      1|	if (fd >= 0) {
  ------------------
  |  Branch (517:6): [True: 0, False: 1]
  ------------------
  518|      0|		m_close(fd);
  519|      0|	}
  520|      1|	return ret;
  521|      0|}
m_close:
  565|  14.4k|void m_close(int fd) {
  566|  14.4k|	int val;
  567|       |
  568|  14.4k|	if (fd < 0) {
  ------------------
  |  Branch (568:6): [True: 3.57k, False: 10.8k]
  ------------------
  569|  3.57k|		return;
  570|  3.57k|	}
  571|       |
  572|  10.8k|	do {
  573|  10.8k|		val = close(fd);
  ------------------
  |  |   56|  10.8k|#define close(fd) wrapfd_close(fd)
  ------------------
  574|  10.8k|	} while (val < 0 && errno == EINTR);
  ------------------
  |  Branch (574:11): [True: 1.37k, False: 9.49k]
  |  Branch (574:22): [True: 0, False: 1.37k]
  ------------------
  575|       |
  576|  10.8k|	if (val < 0 && errno != EBADF) {
  ------------------
  |  Branch (576:6): [True: 1.37k, False: 9.49k]
  |  Branch (576:17): [True: 0, False: 1.37k]
  ------------------
  577|       |		/* Linux says EIO can happen */
  578|       |		dropbear_exit("Error closing fd %d, %s", fd, strerror(errno));
  579|      0|	}
  580|  10.8k|}
setnonblocking:
  582|  5.40k|void setnonblocking(int fd) {
  583|       |
  584|  5.40k|	int fl = 0;
  585|  5.40k|	TRACE(("setnonblocking: %d", fd))
  586|       |
  587|  5.40k|#if DROPBEAR_FUZZ
  588|  5.40k|	if (fuzz.fuzzing) {
  ------------------
  |  Branch (588:6): [True: 5.40k, False: 0]
  ------------------
  589|  5.40k|		return;
  590|  5.40k|	}
  591|      0|#endif
  592|      0|	fl = fcntl(fd, F_GETFL, 0);
  593|      0|	if (fl == -1) {
  ------------------
  |  Branch (593:6): [True: 0, False: 0]
  ------------------
  594|       |		/* F_GETFL shouldn't fail */
  595|      0|		dropbear_exit("Couldn't set nonblocking");
  596|      0|	}
  597|       |
  598|      0|	if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1) {
  ------------------
  |  Branch (598:6): [True: 0, False: 0]
  ------------------
  599|      0|		if (errno == ENODEV) {
  ------------------
  |  Branch (599:7): [True: 0, False: 0]
  ------------------
  600|       |			/* Some devices (like /dev/null redirected in)
  601|       |			 * can't be set to non-blocking */
  602|      0|			TRACE(("ignoring ENODEV for setnonblocking"))
  603|      0|		} else {
  604|      0|			dropbear_exit("Couldn't set nonblocking");
  605|      0|		}
  606|      0|	}
  607|      0|	TRACE(("leave setnonblocking"))
  608|      0|}
disallow_core:
  610|      1|void disallow_core() {
  611|      1|	struct rlimit lim = {0};
  612|      1|	if (getrlimit(RLIMIT_CORE, &lim) < 0) {
  ------------------
  |  Branch (612:6): [True: 0, False: 1]
  ------------------
  613|      0|		TRACE(("getrlimit(RLIMIT_CORE) failed"));
  614|      0|	}
  615|      1|	lim.rlim_cur = 0;
  616|      1|	if (setrlimit(RLIMIT_CORE, &lim) < 0) {
  ------------------
  |  Branch (616:6): [True: 0, False: 1]
  ------------------
  617|      0|		TRACE(("setrlimit(RLIMIT_CORE) failed"));
  618|      0|	}
  619|      1|}
expand_homedir_path_home:
  647|      2|char * expand_homedir_path_home(const char *inpath, const char *homedir) {
  648|      2|	if (strncmp(inpath, "~/", 2) == 0 && homedir) {
  ------------------
  |  Branch (648:6): [True: 2, False: 0]
  |  Branch (648:39): [True: 2, False: 0]
  ------------------
  649|      2|		size_t len = strlen(inpath)-2 + strlen(homedir) + 2;
  650|      2|		char *buf = m_malloc(len);
  651|      2|		snprintf(buf, len, "%s/%s", homedir, inpath+2);
  652|      2|		return buf;
  653|      2|	}
  654|       |	/* Fallback */
  655|      0|	return m_strdup(inpath);
  656|      2|}
expand_homedir_path:
  660|      2|char * expand_homedir_path(const char *inpath) {
  661|      2|	struct passwd *pw = NULL;
  662|      2|	char *homedir = getenv("HOME");
  663|       |
  664|      2|	if (!homedir) {
  ------------------
  |  Branch (664:6): [True: 0, False: 2]
  ------------------
  665|      0|		pw = getpwuid(getuid());
  ------------------
  |  |  109|      0|#define getpwuid(x) fuzz_getpwuid(x)
  ------------------
  666|      0|		if (pw) {
  ------------------
  |  Branch (666:7): [True: 0, False: 0]
  ------------------
  667|      0|			homedir = pw->pw_dir;
  668|      0|		}
  669|      0|	}
  670|      2|	return expand_homedir_path_home(inpath, homedir);
  671|      2|}
gettime_wrapper:
  686|   416k|void gettime_wrapper(struct timespec *now) {
  687|   416k|	struct timeval tv;
  688|   416k|#if DROPBEAR_FUZZ
  689|   416k|	if (fuzz.fuzzing) {
  ------------------
  |  Branch (689:6): [True: 416k, False: 0]
  ------------------
  690|       |		/* time stands still when fuzzing */
  691|   416k|		now->tv_sec = 5;
  692|   416k|		now->tv_nsec = 0;
  693|   416k|	}
  694|   416k|#endif
  695|       |
  696|   416k|#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
  697|       |	/* POSIX monotonic clock. Newer Linux, BSD, MacOSX >10.12 */
  698|   416k|	if (clock_gettime(CLOCK_MONOTONIC, now) == 0) {
  ------------------
  |  Branch (698:6): [True: 416k, False: 0]
  ------------------
  699|   416k|		return;
  700|   416k|	}
  701|      0|#endif
  702|       |
  703|      0|#if defined(__linux__) && defined(SYS_clock_gettime)
  704|      0|	{
  705|       |	/* Old linux toolchain - kernel might support it but not the build headers */
  706|       |	/* Also glibc <2.17 requires -lrt which we neglect to add */
  707|      0|	static int linux_monotonic_failed = 0;
  708|      0|	if (!linux_monotonic_failed) {
  ------------------
  |  Branch (708:6): [True: 0, False: 0]
  ------------------
  709|       |		/* CLOCK_MONOTONIC isn't in some headers */
  710|      0|		int clock_source_monotonic = 1; 
  711|      0|		if (syscall(SYS_clock_gettime, clock_source_monotonic, now) == 0) {
  ------------------
  |  Branch (711:7): [True: 0, False: 0]
  ------------------
  712|      0|			return;
  713|      0|		} else {
  714|       |			/* Don't try again */
  715|      0|			linux_monotonic_failed = 1;
  716|      0|		}
  717|      0|	}
  718|      0|	}
  719|      0|#endif /* linux fallback clock_gettime */
  720|       |
  721|       |#if defined(HAVE_MACH_ABSOLUTE_TIME)
  722|       |	{
  723|       |	/* OS X pre 10.12, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
  724|       |	static mach_timebase_info_data_t timebase_info;
  725|       |	uint64_t scaled_time;
  726|       |	if (timebase_info.denom == 0) {
  727|       |		mach_timebase_info(&timebase_info);
  728|       |	}
  729|       |	scaled_time = mach_absolute_time() * timebase_info.numer / timebase_info.denom;
  730|       |	now->tv_sec = scaled_time / 1000000000;
  731|       |	now->tv_nsec = scaled_time % 1000000000;
  732|       |	}
  733|       |#endif /* osx mach_absolute_time */
  734|       |
  735|       |	/* Fallback for everything else - this will sometimes go backwards */
  736|      0|	gettimeofday(&tv, NULL);
  737|      0|	now->tv_sec = tv.tv_sec;
  738|      0|	now->tv_nsec = 1000*(long)tv.tv_usec;
  739|      0|}
monotonic_now:
  742|   416k|time_t monotonic_now() {
  743|   416k|	struct timespec ts;
  744|   416k|	gettime_wrapper(&ts);
  745|   416k|	return ts.tv_sec;
  746|   416k|}

dss_key_free:
  122|      2|void dss_key_free(dropbear_dss_key *key) {
  123|       |
  124|      2|	TRACE2(("enter dsa_key_free"))
  125|      2|	if (key == NULL) {
  ------------------
  |  Branch (125:6): [True: 2, False: 0]
  ------------------
  126|      2|		TRACE2(("enter dsa_key_free: key == NULL"))
  127|      2|		return;
  128|      2|	}
  129|      0|	m_mp_free_multi(&key->p, &key->q, &key->g, &key->y, &key->x, NULL);
  130|       |	m_free(key);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  131|      0|	TRACE2(("leave dsa_key_free"))
  132|      0|}

dropbear_ecc_fill_dp:
   47|      1|void dropbear_ecc_fill_dp() {
   48|      1|	struct dropbear_ecc_curve **curve;
   49|       |	/* libtomcrypt guarantees they're ordered by size */
   50|      1|	const ltc_ecc_set_type *dp = ltc_ecc_sets;
   51|      4|	for (curve = dropbear_ecc_curves; *curve; curve++) {
  ------------------
  |  Branch (51:36): [True: 3, False: 1]
  ------------------
   52|      5|		for (;dp->size > 0; dp++) {
  ------------------
  |  Branch (52:9): [True: 5, False: 0]
  ------------------
   53|      5|			if (dp->size == (*curve)->ltc_size) {
  ------------------
  |  Branch (53:8): [True: 3, False: 2]
  ------------------
   54|      3|				(*curve)->dp = dp;
   55|      3|				break;
   56|      3|			}
   57|      5|		}
   58|      3|		if (!(*curve)->dp) {
  ------------------
  |  Branch (58:7): [True: 0, False: 3]
  ------------------
   59|      0|			dropbear_exit("Missing ECC params %s", (*curve)->name);
   60|      0|		}
   61|      3|	}
   62|      1|}

signkey_is_ecdsa:
   11|      1|{
   12|      1|	return type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
  ------------------
  |  Branch (12:9): [True: 0, False: 1]
  ------------------
   13|      1|		|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
  ------------------
  |  Branch (13:6): [True: 0, False: 1]
  ------------------
   14|      1|		|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP521;
  ------------------
  |  Branch (14:6): [True: 0, False: 1]
  ------------------
   15|      1|}

buf_get_ed25519_priv_key:
   78|      1|int buf_get_ed25519_priv_key(buffer *buf, dropbear_ed25519_key *key) {
   79|       |
   80|      1|	unsigned int len;
   81|       |
   82|      1|	TRACE(("enter buf_get_ed25519_priv_key"))
   83|      1|	dropbear_assert(key != NULL);
  ------------------
  |  |   84|      1|#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
  |  |  ------------------
  |  |  |  Branch (84:37): [True: 0, False: 1]
  |  |  |  Branch (84:93): [Folded, False: 1]
  |  |  ------------------
  ------------------
   84|       |
   85|      1|	buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
  ------------------
  |  |  119|      1|#define SSH_SIGNKEY_ED25519_LEN 11
  ------------------
   86|       |
   87|      1|	len = buf_getint(buf);
   88|      1|	if (len != CURVE25519_LEN*2 || buf->len - buf->pos < len) {
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
  |  Branch (88:6): [True: 0, False: 1]
  |  Branch (88:33): [True: 0, False: 1]
  ------------------
   89|      0|		TRACE(("leave buf_get_ed25519_priv_key: failure"))
   90|      0|		return DROPBEAR_FAILURE;
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
   91|      0|	}
   92|       |
   93|      1|	memcpy(key->priv, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
              	memcpy(key->priv, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
   94|      1|	buf_incrpos(buf, CURVE25519_LEN);
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
   95|      1|	memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
              	memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
   96|      1|	buf_incrpos(buf, CURVE25519_LEN);
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
   97|       |
   98|      1|	TRACE(("leave buf_get_ed25519_priv_key: success"))
   99|      1|	return DROPBEAR_SUCCESS;
  ------------------
  |  |  111|      1|#define DROPBEAR_SUCCESS 0
  ------------------
  100|      1|}
ed25519_key_free:
  103|      3|void ed25519_key_free(dropbear_ed25519_key *key) {
  104|       |
  105|      3|	TRACE2(("enter ed25519_key_free"))
  106|       |
  107|      3|	if (key == NULL) {
  ------------------
  |  Branch (107:6): [True: 2, False: 1]
  ------------------
  108|      2|		TRACE2(("leave ed25519_key_free: key == NULL"))
  109|      2|		return;
  110|      2|	}
  111|      1|	m_burn(key->priv, CURVE25519_LEN);
  ------------------
  |  |   34|      1|#define CURVE25519_LEN 32
  ------------------
  112|      1|	m_free(key);
  ------------------
  |  |   24|      1|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1]
  |  |  ------------------
  ------------------
  113|       |
  114|      1|	TRACE2(("leave ed25519_key_free"))
  115|      1|}

list_append:
    5|      1|void list_append(m_list *list, void *item) {
    6|      1|	m_list_elem *elem;
    7|       |	
    8|      1|	elem = m_malloc(sizeof(*elem));
    9|      1|	elem->item = item;
   10|      1|	elem->list = list;
   11|      1|	elem->next = NULL;
   12|      1|	if (!list->first) {
  ------------------
  |  Branch (12:6): [True: 1, False: 0]
  ------------------
   13|      1|		list->first = elem;
   14|      1|		elem->prev = NULL;
   15|      1|	} else {
   16|      0|		elem->prev = list->last;
   17|      0|		list->last->next = elem;
   18|      0|	}
   19|      1|	list->last = elem;
   20|      1|}
list_new:
   22|      3|m_list * list_new() {
   23|      3|	m_list *ret = m_malloc(sizeof(m_list));
   24|       |	ret->first = ret->last = NULL;
   25|      3|	return ret;
   26|      3|}
list_remove:
   28|      1|void * list_remove(m_list_elem *elem) {
   29|      1|	void *item = elem->item;
   30|      1|	m_list *list = elem->list;
   31|      1|	if (list->first == elem)
  ------------------
  |  Branch (31:6): [True: 1, False: 0]
  ------------------
   32|      1|	{
   33|      1|		list->first = elem->next;
   34|      1|	}
   35|      1|	if (list->last == elem)
  ------------------
  |  Branch (35:6): [True: 1, False: 0]
  ------------------
   36|      1|	{
   37|      1|		list->last = elem->prev;
   38|      1|	}
   39|      1|	if (elem->prev)
  ------------------
  |  Branch (39:6): [True: 0, False: 1]
  ------------------
   40|      0|	{
   41|      0|		elem->prev->next = elem->next;
   42|      0|	}
   43|      1|	if (elem->next)
  ------------------
  |  Branch (43:6): [True: 0, False: 1]
  ------------------
   44|      0|	{
   45|      0|		elem->next->prev = elem->prev;
   46|      0|	}
   47|       |	m_free(elem);
  ------------------
  |  |   24|      1|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1]
  |  |  ------------------
  ------------------
   48|      1|	return item;
   49|      1|}

listeners_initialise:
   30|  2.70k|void listeners_initialise() {
   31|       |
   32|       |	/* just one slot to start with */
   33|  2.70k|	ses.listeners = (struct Listener**)m_malloc(sizeof(struct Listener*));
   34|  2.70k|	ses.listensize = 1;
   35|  2.70k|	ses.listeners[0] = NULL;
   36|       |
   37|  2.70k|}
set_listener_fds:
   39|   139k|void set_listener_fds(fd_set * readfds) {
   40|       |
   41|   139k|	unsigned int i, j;
   42|   139k|	struct Listener *listener;
   43|       |
   44|       |	/* check each in turn */
   45|   278k|	for (i = 0; i < ses.listensize; i++) {
  ------------------
  |  Branch (45:14): [True: 139k, False: 139k]
  ------------------
   46|   139k|		listener = ses.listeners[i];
   47|   139k|		if (listener != NULL) {
  ------------------
  |  Branch (47:7): [True: 0, False: 139k]
  ------------------
   48|      0|			for (j = 0; j < listener->nsocks; j++) {
  ------------------
  |  Branch (48:16): [True: 0, False: 0]
  ------------------
   49|       |				FD_SET(listener->socks[j], readfds);
   50|      0|			}
   51|      0|		}
   52|   139k|	}
   53|   139k|}
handle_listeners:
   56|   136k|void handle_listeners(const fd_set * readfds) {
   57|       |
   58|   136k|	unsigned int i, j;
   59|   136k|	struct Listener *listener;
   60|   136k|	int sock;
   61|       |
   62|       |	/* check each in turn */
   63|   272k|	for (i = 0; i < ses.listensize; i++) {
  ------------------
  |  Branch (63:14): [True: 136k, False: 136k]
  ------------------
   64|   136k|		listener = ses.listeners[i];
   65|   136k|		if (listener != NULL) {
  ------------------
  |  Branch (65:7): [True: 0, False: 136k]
  ------------------
   66|      0|			for (j = 0; j < listener->nsocks; j++) {
  ------------------
  |  Branch (66:16): [True: 0, False: 0]
  ------------------
   67|      0|				sock = listener->socks[j];
   68|      0|				if (FD_ISSET(sock, readfds)) {
  ------------------
  |  Branch (68:9): [True: 0, False: 0]
  ------------------
   69|      0|					listener->acceptor(listener, sock);
   70|      0|				}
   71|      0|			}
   72|      0|		}
   73|   136k|	}
   74|   136k|} /* Woo brace matching */
remove_all_listeners:
  166|  2.70k|void remove_all_listeners(void) {
  167|  2.70k|	unsigned int i;
  168|  5.40k|	for (i = 0; i < ses.listensize; i++) {
  ------------------
  |  Branch (168:14): [True: 2.70k, False: 2.70k]
  ------------------
  169|  2.70k|		if (ses.listeners[i]) {
  ------------------
  |  Branch (169:7): [True: 0, False: 2.70k]
  ------------------
  170|      0|			remove_listener(ses.listeners[i]);
  171|      0|		}
  172|  2.70k|	}
  173|       |	m_free(ses.listeners);
  ------------------
  |  |   24|  2.70k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2.70k]
  |  |  ------------------
  ------------------
  174|  2.70k|}

remove_connect_pending:
  291|  2.70k|void remove_connect_pending() {
  292|  2.70k|	while (ses.conn_pending.first) {
  ------------------
  |  Branch (292:9): [True: 0, False: 2.70k]
  ------------------
  293|      0|		struct dropbear_progress_connection *c = ses.conn_pending.first->item;
  294|      0|		remove_connect(c, ses.conn_pending.first);
  295|      0|	}
  296|  2.70k|}
set_connect_fds:
  299|   139k|void set_connect_fds(fd_set *writefd) {
  300|   139k|	m_list_elem *iter;
  301|   139k|	iter = ses.conn_pending.first;
  302|   139k|	while (iter) {
  ------------------
  |  Branch (302:9): [True: 0, False: 139k]
  ------------------
  303|      0|		m_list_elem *next_iter = iter->next;
  304|      0|		struct dropbear_progress_connection *c = iter->item;
  305|       |		/* Set one going */
  306|      0|		while (c->res_iter && c->sock < 0) {
  ------------------
  |  Branch (306:10): [True: 0, False: 0]
  |  Branch (306:25): [True: 0, False: 0]
  ------------------
  307|      0|			connect_try_next(c);
  308|      0|		}
  309|      0|		if (c->sock >= 0) {
  ------------------
  |  Branch (309:7): [True: 0, False: 0]
  ------------------
  310|      0|			FD_SET(c->sock, writefd);
  311|      0|		} else {
  312|       |			/* Final failure */
  313|      0|			if (!c->errstring) {
  ------------------
  |  Branch (313:8): [True: 0, False: 0]
  ------------------
  314|      0|				c->errstring = m_strdup("unexpected failure");
  315|      0|			}
  316|      0|			c->cb(DROPBEAR_FAILURE, -1, c->cb_data, c->errstring);
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  317|      0|			remove_connect(c, iter);
  318|      0|		}
  319|      0|		iter = next_iter;
  320|      0|	}
  321|   139k|}
handle_connect_fds:
  323|   136k|void handle_connect_fds(const fd_set *writefd) {
  324|   136k|	m_list_elem *iter;
  325|   136k|	for (iter = ses.conn_pending.first; iter; iter = iter->next) {
  ------------------
  |  Branch (325:38): [True: 0, False: 136k]
  ------------------
  326|      0|		int val;
  327|      0|		socklen_t vallen = sizeof(val);
  328|      0|		struct dropbear_progress_connection *c = iter->item;
  329|       |
  330|      0|		if (c->sock < 0 || !FD_ISSET(c->sock, writefd)) {
  ------------------
  |  Branch (330:7): [True: 0, False: 0]
  |  Branch (330:22): [True: 0, False: 0]
  ------------------
  331|      0|			continue;
  332|      0|		}
  333|       |
  334|      0|		TRACE(("handling %s port %s socket %d", c->remotehost, c->remoteport, c->sock));
  335|       |
  336|      0|		if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &val, &vallen) != 0) {
  ------------------
  |  Branch (336:7): [True: 0, False: 0]
  ------------------
  337|      0|			TRACE(("handle_connect_fds getsockopt(%d) SO_ERROR failed: %s", c->sock, strerror(errno)))
  338|       |			/* This isn't expected to happen - Unix has surprises though, continue gracefully. */
  339|      0|			m_close(c->sock);
  340|      0|			c->sock = -1;
  341|      0|		} else if (val != 0) {
  ------------------
  |  Branch (341:14): [True: 0, False: 0]
  ------------------
  342|       |			/* Connect failed */
  343|      0|			TRACE(("connect to %s port %s failed.", c->remotehost, c->remoteport))
  344|      0|			m_close(c->sock);
  345|      0|			c->sock = -1;
  346|       |
  347|      0|			m_free(c->errstring);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  348|      0|			c->errstring = m_strdup(strerror(val));
  349|      0|		} else {
  350|       |			/* New connection has been established */
  351|      0|			c->cb(DROPBEAR_SUCCESS, c->sock, c->cb_data, NULL);
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  352|      0|			remove_connect(c, iter);
  353|      0|			TRACE(("leave handle_connect_fds - success"))
  354|       |			/* Must return here - remove_connect() invalidates iter */
  355|      0|			return; 
  356|      0|		}
  357|      0|	}
  358|   136k|}
packet_queue_to_iovec:
  364|  23.8k|void packet_queue_to_iovec(const struct Queue *queue, struct iovec *iov, unsigned int *iov_count) {
  365|  23.8k|	struct Link *l;
  366|  23.8k|	unsigned int i;
  367|  23.8k|	int len;
  368|  23.8k|	buffer *writebuf;
  369|       |
  370|       |#ifndef IOV_MAX
  371|       |	#if (defined(__CYGWIN__) || defined(__GNU__)) && !defined(UIO_MAXIOV)
  372|       |		#define IOV_MAX 1024
  373|       |	#elif defined(__sgi)
  374|       |		#define IOV_MAX 512 
  375|       |	#else 
  376|       |		#define IOV_MAX UIO_MAXIOV
  377|       |	#endif
  378|       |#endif
  379|       |
  380|  23.8k|	*iov_count = MIN(MIN(queue->count, IOV_MAX), *iov_count);
  ------------------
  |  Branch (380:15): [True: 23.8k, False: 0]
  |  Branch (380:15): [True: 23.8k, False: 0]
  |  Branch (380:15): [True: 23.8k, False: 0]
  ------------------
  381|       |
  382|  50.3k|	for (l = queue->head, i = 0; i < *iov_count; l = l->link, i++)
  ------------------
  |  Branch (382:31): [True: 26.5k, False: 23.8k]
  ------------------
  383|  26.5k|	{
  384|  26.5k|		writebuf = (buffer*)l->item;
  385|  26.5k|		len = writebuf->len - writebuf->pos;
  386|  26.5k|		dropbear_assert(len > 0);
  ------------------
  |  |   84|  26.5k|#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
  |  |  ------------------
  |  |  |  Branch (84:37): [True: 0, False: 26.5k]
  |  |  |  Branch (84:93): [Folded, False: 26.5k]
  |  |  ------------------
  ------------------
  387|  26.5k|		TRACE2(("write_packet writev #%d len %d/%d", i,
  388|  26.5k|				len, writebuf->len))
  389|  26.5k|		iov[i].iov_base = buf_getptr(writebuf, len);
  390|  26.5k|		iov[i].iov_len = len;
  391|  26.5k|	}
  392|  23.8k|}
packet_queue_consume:
  394|  23.8k|void packet_queue_consume(struct Queue *queue, ssize_t written) {
  395|  23.8k|	buffer *writebuf;
  396|  23.8k|	int len;
  397|  47.6k|	while (written > 0) {
  ------------------
  |  Branch (397:9): [True: 23.8k, False: 23.8k]
  ------------------
  398|  23.8k|		writebuf = (buffer*)examine(queue);
  399|  23.8k|		len = writebuf->len - writebuf->pos;
  400|  23.8k|		if (len > written) {
  ------------------
  |  Branch (400:7): [True: 0, False: 23.8k]
  ------------------
  401|       |			/* partial buffer write */
  402|      0|			buf_incrpos(writebuf, written);
  403|      0|			written = 0;
  404|  23.8k|		} else {
  405|  23.8k|			written -= len;
  406|  23.8k|			dequeue(queue);
  407|  23.8k|			buf_free(writebuf);
  408|  23.8k|		}
  409|  23.8k|	}
  410|  23.8k|}
set_sock_priority:
  430|  2.70k|void set_sock_priority(int sock, enum dropbear_prio prio) {
  431|       |
  432|  2.70k|	int rc;
  433|  2.70k|	int val;
  434|       |
  435|  2.70k|#if DROPBEAR_FUZZ
  436|  2.70k|	if (fuzz.fuzzing) {
  ------------------
  |  Branch (436:6): [True: 2.70k, False: 0]
  ------------------
  437|  2.70k|		TRACE(("fuzzing skips set_sock_prio"))
  438|  2.70k|		return;
  439|  2.70k|	}
  440|      0|#endif
  441|       |	/* Don't log ENOTSOCK errors so that this can harmlessly be called
  442|       |	 * on a client '-J' proxy pipe */
  443|       |
  444|      0|	if (opts.disable_ip_tos == 0) {
  ------------------
  |  Branch (444:6): [True: 0, False: 0]
  ------------------
  445|      0|#ifdef IP_TOS
  446|       |	/* Set the DSCP field for outbound IP packet priority.
  447|       |	rfc4594 has some guidance to meanings.
  448|       |
  449|       |	We set AF21 as "Low-Latency" class for interactive (tty session,
  450|       |	also handshake/setup packets). Other traffic is left at the default.
  451|       |
  452|       |	OpenSSH at present uses AF21/CS1, rationale
  453|       |	https://cvsweb.openbsd.org/src/usr.bin/ssh/readconf.c#rev1.284
  454|       |
  455|       |	Old Dropbear/OpenSSH and Debian/Ubuntu OpenSSH (at Jan 2022) use
  456|       |	IPTOS_LOWDELAY/IPTOS_THROUGHPUT
  457|       |
  458|       |	DSCP constants are from Linux headers, applicable to other platforms
  459|       |	such as macos.
  460|       |	*/
  461|      0|	if (prio == DROPBEAR_PRIO_LOWDELAY) {
  ------------------
  |  Branch (461:6): [True: 0, False: 0]
  ------------------
  462|      0|		val = 0x48; /* IPTOS_DSCP_AF21 */
  463|      0|	} else {
  464|      0|		val = 0; /* default */
  465|      0|	}
  466|      0|#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
  467|      0|	rc = setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)&val, sizeof(val));
  468|      0|	if (rc < 0 && errno != ENOTSOCK) {
  ------------------
  |  Branch (468:6): [True: 0, False: 0]
  |  Branch (468:16): [True: 0, False: 0]
  ------------------
  469|      0|		TRACE(("Couldn't set IPV6_TCLASS (%s)", strerror(errno)));
  470|      0|	}
  471|      0|#endif
  472|      0|	rc = setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val));
  473|      0|	if (rc < 0 && errno != ENOTSOCK) {
  ------------------
  |  Branch (473:6): [True: 0, False: 0]
  |  Branch (473:16): [True: 0, False: 0]
  ------------------
  474|      0|		TRACE(("Couldn't set IP_TOS (%s)", strerror(errno)));
  475|      0|	}
  476|      0|#endif /* IP_TOS */
  477|      0|	}
  478|       |
  479|      0|#ifdef HAVE_LINUX_PKT_SCHED_H
  480|       |	/* Set scheduling priority within the local Linux network stack */
  481|      0|	if (prio == DROPBEAR_PRIO_LOWDELAY) {
  ------------------
  |  Branch (481:6): [True: 0, False: 0]
  ------------------
  482|      0|		val = TC_PRIO_INTERACTIVE;
  483|      0|	} else {
  484|      0|		val = 0;
  485|      0|	}
  486|       |	/* linux specific, sets QoS class. see tc-prio(8) */
  487|      0|	rc = setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &val, sizeof(val));
  488|      0|	if (rc < 0 && errno != ENOTSOCK) {
  ------------------
  |  Branch (488:6): [True: 0, False: 0]
  |  Branch (488:16): [True: 0, False: 0]
  ------------------
  489|      0|		TRACE(("Couldn't set SO_PRIORITY (%s)", strerror(errno)))
  490|      0|    }
  491|      0|#endif
  492|       |
  493|      0|}

write_packet:
   58|  23.8k|void write_packet() {
   59|       |
   60|  23.8k|	ssize_t written;
   61|  23.8k|#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
   62|       |	/* 50 is somewhat arbitrary */
   63|  23.8k|	unsigned int iov_count = 50;
   64|  23.8k|	struct iovec iov[50];
   65|       |#else
   66|       |	int len;
   67|       |	buffer* writebuf;
   68|       |#endif
   69|       |	
   70|  23.8k|	TRACE2(("enter write_packet"))
   71|  23.8k|	dropbear_assert(!isempty(&ses.writequeue));
  ------------------
  |  |   84|  23.8k|#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
  |  |  ------------------
  |  |  |  Branch (84:37): [True: 0, False: 23.8k]
  |  |  |  Branch (84:93): [Folded, False: 23.8k]
  |  |  ------------------
  ------------------
   72|       |
   73|  23.8k|#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
   74|       |
   75|  23.8k|	packet_queue_to_iovec(&ses.writequeue, iov, &iov_count);
   76|       |	/* This may return EAGAIN. The main loop sometimes
   77|       |	calls write_packet() without bothering to test with select() since
   78|       |	it's likely to be necessary */
   79|  23.8k|#if DROPBEAR_FUZZ
   80|  23.8k|	if (fuzz.fuzzing) {
  ------------------
  |  Branch (80:6): [True: 23.8k, False: 0]
  ------------------
   81|       |		/* pretend to write one packet at a time */
   82|       |		/* TODO(fuzz): randomise amount written based on the fuzz input */
   83|  23.8k|		written = iov[0].iov_len;
   84|  23.8k|	}
   85|      0|	else
   86|      0|#endif
   87|      0|	{
   88|      0|	written = writev(ses.sock_out, iov, iov_count);
   89|      0|	if (written < 0) {
  ------------------
  |  Branch (89:6): [True: 0, False: 0]
  ------------------
   90|      0|		if (errno == EINTR || errno == EAGAIN) {
  ------------------
  |  Branch (90:7): [True: 0, False: 0]
  |  Branch (90:25): [True: 0, False: 0]
  ------------------
   91|      0|			TRACE2(("leave write_packet: EINTR"))
   92|      0|			return;
   93|      0|		} else {
   94|      0|			dropbear_exit("Error writing: %s", strerror(errno));
   95|      0|		}
   96|      0|	}
   97|      0|	}
   98|       |
   99|  23.8k|	packet_queue_consume(&ses.writequeue, written);
  100|  23.8k|	ses.writequeue_len -= written;
  101|       |
  102|  23.8k|	if (written == 0) {
  ------------------
  |  Branch (102:6): [True: 0, False: 23.8k]
  ------------------
  103|      0|		ses.remoteclosed();
  104|      0|	}
  105|       |
  106|       |#else /* No writev () */
  107|       |#if DROPBEAR_FUZZ
  108|       |	_Static_assert(0, "No fuzzing code for no-writev writes");
  109|       |#endif
  110|       |	/* Get the next buffer in the queue of encrypted packets to write*/
  111|       |	writebuf = (buffer*)examine(&ses.writequeue);
  112|       |
  113|       |	len = writebuf->len - writebuf->pos;
  114|       |	dropbear_assert(len > 0);
  115|       |	/* Try to write as much as possible */
  116|       |	written = write(ses.sock_out, buf_getptr(writebuf, len), len);
  117|       |
  118|       |	if (written < 0) {
  119|       |		if (errno == EINTR || errno == EAGAIN) {
  120|       |			TRACE2(("leave writepacket: EINTR"))
  121|       |			return;
  122|       |		} else {
  123|       |			dropbear_exit("Error writing: %s", strerror(errno));
  124|       |		}
  125|       |	} 
  126|       |
  127|       |	if (written == 0) {
  128|       |		ses.remoteclosed();
  129|       |	}
  130|       |
  131|       |	ses.writequeue_len -= written;
  132|       |
  133|       |	if (written == len) {
  134|       |		/* We've finished with the packet, free it */
  135|       |		dequeue(&ses.writequeue);
  136|       |		buf_free(writebuf);
  137|       |		writebuf = NULL;
  138|       |	} else {
  139|       |		/* More packet left to write, leave it in the queue for later */
  140|       |		buf_incrpos(writebuf, written);
  141|       |	}
  142|       |#endif /* writev */
  143|       |
  144|  23.8k|	TRACE2(("leave write_packet"))
  145|  23.8k|}
read_packet:
  150|   124k|void read_packet() {
  151|       |
  152|   124k|	int len;
  153|   124k|	unsigned int maxlen;
  154|   124k|	unsigned char blocksize;
  155|       |
  156|   124k|	TRACE2(("enter read_packet"))
  157|   124k|	blocksize = ses.keys->recv.algo_crypt->blocksize;
  158|       |	
  159|   124k|	if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
  ------------------
  |  Branch (159:6): [True: 33.2k, False: 91.2k]
  |  Branch (159:29): [True: 54.6k, False: 36.6k]
  ------------------
  160|  87.8k|		int ret;
  161|       |		/* In the first blocksize of a packet */
  162|       |
  163|       |		/* Read the first blocksize of the packet, so we can decrypt it and
  164|       |		 * find the length of the whole packet */
  165|  87.8k|		ret = read_packet_init();
  166|       |
  167|  87.8k|		if (ret == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|  87.8k|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (167:7): [True: 54.6k, False: 33.2k]
  ------------------
  168|       |			/* didn't read enough to determine the length */
  169|  54.6k|			TRACE2(("leave read_packet: packetinit done"))
  170|  54.6k|			return;
  171|  54.6k|		}
  172|  87.8k|	}
  173|       |
  174|       |	/* Attempt to read the remainder of the packet, note that there
  175|       |	 * mightn't be any available (EAGAIN) */
  176|  69.8k|	maxlen = ses.readbuf->len - ses.readbuf->pos;
  177|  69.8k|	if (maxlen == 0) {
  ------------------
  |  Branch (177:6): [True: 17.9k, False: 51.9k]
  ------------------
  178|       |		/* Occurs when the packet is only a single block long and has all
  179|       |		 * been read in read_packet_init().  Usually means that MAC is disabled
  180|       |		 */
  181|  17.9k|		len = 0;
  182|  51.9k|	} else {
  183|  51.9k|		len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
  ------------------
  |  |   55|  51.9k|#define read(fd, buf, count) wrapfd_read(fd, buf, count)
  ------------------
  184|       |
  185|  51.9k|		if (len == 0) {
  ------------------
  |  Branch (185:7): [True: 104, False: 51.8k]
  ------------------
  186|    104|			ses.remoteclosed();
  187|    104|		}
  188|       |
  189|  51.9k|		if (len < 0) {
  ------------------
  |  Branch (189:7): [True: 68, False: 51.8k]
  ------------------
  190|     68|			if (errno == EINTR || errno == EAGAIN) {
  ------------------
  |  Branch (190:8): [True: 67, False: 1]
  |  Branch (190:26): [True: 0, False: 1]
  ------------------
  191|     67|				TRACE2(("leave read_packet: EINTR or EAGAIN"))
  192|     67|				return;
  193|     67|			} else {
  194|      1|				dropbear_exit("Error reading: %s", strerror(errno));
  195|      1|			}
  196|     68|		}
  197|       |
  198|  51.8k|		buf_incrpos(ses.readbuf, len);
  199|  51.8k|	}
  200|       |
  201|  69.7k|	if ((unsigned int)len == maxlen) {
  ------------------
  |  Branch (201:6): [True: 31.9k, False: 37.8k]
  ------------------
  202|       |		/* The whole packet has been read */
  203|  31.9k|		decrypt_packet();
  204|       |		/* The main select() loop process_packet() to
  205|       |		 * handle the packet contents... */
  206|  31.9k|	}
  207|  69.7k|	TRACE2(("leave read_packet"))
  208|  69.7k|}
decrypt_packet:
  298|  31.9k|void decrypt_packet() {
  299|       |
  300|  31.9k|	unsigned char blocksize;
  301|  31.9k|	unsigned char macsize;
  302|  31.9k|	unsigned int padlen;
  303|  31.9k|	unsigned int len;
  304|       |
  305|  31.9k|	TRACE2(("enter decrypt_packet"))
  306|  31.9k|	blocksize = ses.keys->recv.algo_crypt->blocksize;
  307|  31.9k|	macsize = ses.keys->recv.algo_mac->hashsize;
  308|       |
  309|  31.9k|	ses.kexstate.datarecv += ses.readbuf->len;
  310|       |
  311|  31.9k|#if DROPBEAR_AEAD_MODE
  312|  31.9k|	if (ses.keys->recv.crypt_mode->aead_crypt) {
  ------------------
  |  Branch (312:6): [True: 0, False: 31.9k]
  ------------------
  313|       |		/* first blocksize is not decrypted yet */
  314|      0|		buf_setpos(ses.readbuf, 0);
  315|       |
  316|       |		/* decrypt it in-place */
  317|      0|		len = ses.readbuf->len - macsize - ses.readbuf->pos;
  318|      0|		if (ses.keys->recv.crypt_mode->aead_crypt(ses.recvseq,
  ------------------
  |  Branch (318:7): [True: 0, False: 0]
  ------------------
  319|      0|					buf_getptr(ses.readbuf, len + macsize),
  320|      0|					buf_getwriteptr(ses.readbuf, len),
  321|      0|					len, macsize,
  322|      0|					&ses.keys->recv.cipher_state, LTC_DECRYPT) != CRYPT_OK) {
  ------------------
  |  |   70|      0|#define LTC_DECRYPT 1
  ------------------
  323|      0|			dropbear_exit("Error decrypting");
  324|      0|		}
  325|      0|		buf_incrpos(ses.readbuf, len);
  326|      0|	} else
  327|  31.9k|#endif
  328|  31.9k|	{
  329|       |		/* we've already decrypted the first blocksize in read_packet_init */
  330|  31.9k|		buf_setpos(ses.readbuf, blocksize);
  331|       |
  332|       |		/* decrypt it in-place */
  333|  31.9k|		len = ses.readbuf->len - macsize - ses.readbuf->pos;
  334|  31.9k|		if (ses.keys->recv.crypt_mode->decrypt(
  ------------------
  |  Branch (334:7): [True: 0, False: 31.9k]
  ------------------
  335|  31.9k|					buf_getptr(ses.readbuf, len), 
  336|  31.9k|					buf_getwriteptr(ses.readbuf, len),
  337|  31.9k|					len,
  338|  31.9k|					&ses.keys->recv.cipher_state) != CRYPT_OK) {
  339|      0|			dropbear_exit("Error decrypting");
  340|      0|		}
  341|  31.9k|		buf_incrpos(ses.readbuf, len);
  342|       |
  343|       |		/* check the hmac */
  344|  31.9k|		if (checkmac() != DROPBEAR_SUCCESS) {
  ------------------
  |  |  111|  31.9k|#define DROPBEAR_SUCCESS 0
  ------------------
  |  Branch (344:7): [True: 0, False: 31.9k]
  ------------------
  345|      0|			dropbear_exit("Integrity error");
  346|      0|		}
  347|       |
  348|  31.9k|	}
  349|       |	
  350|  31.9k|#if DROPBEAR_FUZZ
  351|  31.9k|	fuzz_dump(ses.readbuf->data, ses.readbuf->len);
  352|  31.9k|#endif
  353|       |
  354|       |	/* get padding length */
  355|  31.9k|	buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
  ------------------
  |  |   48|  31.9k|#define PACKET_PADDING_OFF 4
  ------------------
  356|  31.9k|	padlen = buf_getbyte(ses.readbuf);
  357|       |		
  358|       |	/* payload length */
  359|       |	/* - 4 - 1 is for LEN and PADLEN values */
  360|  31.9k|	len = ses.readbuf->len - padlen - 4 - 1 - macsize;
  361|  31.9k|	if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
  ------------------
  |  |  555|  31.9k|#define RECV_MAX_PAYLOAD_LEN 32768
  ------------------
              	if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
  ------------------
  |  |   50|  31.9k|#define ZLIB_COMPRESS_EXPANSION (((RECV_MAX_PAYLOAD_LEN/16384)+1)*5 + 6)
  |  |  ------------------
  |  |  |  |  555|  31.9k|#define RECV_MAX_PAYLOAD_LEN 32768
  |  |  ------------------
  ------------------
  |  Branch (361:6): [True: 12, False: 31.9k]
  |  Branch (361:62): [True: 1, False: 31.9k]
  ------------------
  362|     13|		dropbear_exit("Bad packet size %u", len);
  363|     13|	}
  364|       |
  365|  31.9k|	buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF);
  ------------------
  |  |   49|  31.9k|#define PACKET_PAYLOAD_OFF 5
  ------------------
  366|       |
  367|       |#ifndef DISABLE_ZLIB
  368|       |	if (is_compress_recv()) {
  369|       |		/* decompress */
  370|       |		ses.payload = buf_decompress(ses.readbuf, len);
  371|       |		buf_setpos(ses.payload, 0);
  372|       |		ses.payload_beginning = 0;
  373|       |		buf_free(ses.readbuf);
  374|       |	} else 
  375|       |#endif
  376|  31.9k|	{
  377|  31.9k|		ses.payload = ses.readbuf;
  378|  31.9k|		ses.payload_beginning = ses.payload->pos;
  379|  31.9k|		buf_setlen(ses.payload, ses.payload->pos + len);
  380|  31.9k|	}
  381|  31.9k|	ses.readbuf = NULL;
  382|       |
  383|  31.9k|	ses.recvseq++;
  384|       |
  385|  31.9k|	TRACE2(("leave decrypt_packet"))
  386|  31.9k|}
maybe_flush_reply_queue:
  495|   136k|void maybe_flush_reply_queue() {
  496|   136k|	struct packetlist *tmp_item = NULL, *curr_item = NULL;
  497|   136k|	if (!ses.dataallowed)
  ------------------
  |  Branch (497:6): [True: 136k, False: 0]
  ------------------
  498|   136k|	{
  499|   136k|		TRACE(("maybe_empty_reply_queue - no data allowed"))
  500|   136k|		return;
  501|   136k|	}
  502|       |		
  503|      0|	for (curr_item = ses.reply_queue_head; curr_item; ) {
  ------------------
  |  Branch (503:41): [True: 0, False: 0]
  ------------------
  504|      0|		CHECKCLEARTOWRITE();
  505|      0|		buf_putbytes(ses.writepayload,
  506|      0|			curr_item->payload->data, curr_item->payload->len);
  507|       |			
  508|      0|		buf_free(curr_item->payload);
  509|      0|		tmp_item = curr_item;
  510|      0|		curr_item = curr_item->next;
  511|      0|		m_free(tmp_item);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  512|      0|		encrypt_packet();
  513|      0|	}
  514|       |	ses.reply_queue_head = ses.reply_queue_tail = NULL;
  515|      0|}
encrypt_packet:
  519|  24.5k|void encrypt_packet() {
  520|       |
  521|  24.5k|	unsigned char padlen;
  522|  24.5k|	unsigned char blocksize, mac_size;
  523|  24.5k|	buffer * writebuf; /* the packet which will go on the wire. This is 
  524|       |	                      encrypted in-place. */
  525|  24.5k|	unsigned char packet_type;
  526|  24.5k|	unsigned int len, encrypt_buf_size;
  527|  24.5k|	unsigned char mac_bytes[MAX_MAC_LEN];
  528|       |
  529|  24.5k|	time_t now;
  530|       |	
  531|  24.5k|	TRACE2(("enter encrypt_packet()"))
  532|       |
  533|  24.5k|	buf_setpos(ses.writepayload, 0);
  534|  24.5k|	packet_type = buf_getbyte(ses.writepayload);
  535|  24.5k|	buf_setpos(ses.writepayload, 0);
  536|       |
  537|  24.5k|	TRACE2(("encrypt_packet type is %d", packet_type))
  538|       |	
  539|  24.5k|	if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) {
  ------------------
  |  Branch (539:7): [True: 21.8k, False: 2.70k]
  |  Branch (539:27): [True: 3.47k, False: 18.4k]
  ------------------
  540|       |		/* During key exchange only particular packets are allowed.
  541|       |			Since this packet_type isn't OK we just enqueue it to send 
  542|       |			after the KEX, see maybe_flush_reply_queue */
  543|  3.47k|		enqueue_reply_packet();
  544|  3.47k|		return;
  545|  3.47k|	}
  546|       |		
  547|  21.1k|	blocksize = ses.keys->trans.algo_crypt->blocksize;
  548|  21.1k|	mac_size = ses.keys->trans.algo_mac->hashsize;
  549|       |
  550|       |	/* Encrypted packet len is payload+5. We need to then make sure
  551|       |	 * there is enough space for padding or MIN_PACKET_LEN. 
  552|       |	 * Add extra 3 since we need at least 4 bytes of padding */
  553|  21.1k|	encrypt_buf_size = (ses.writepayload->len+4+1) 
  554|  21.1k|		+ MAX(MIN_PACKET_LEN, blocksize) + 3
  ------------------
  |  Branch (554:5): [True: 21.1k, False: 0]
  ------------------
  555|       |	/* add space for the MAC at the end */
  556|  21.1k|				+ mac_size
  557|       |#ifndef DISABLE_ZLIB
  558|       |	/* some extra in case 'compression' makes it larger */
  559|       |				+ ZLIB_COMPRESS_EXPANSION
  560|       |#endif
  561|       |	/* and an extra cleartext (stripped before transmission) byte for the
  562|       |	 * packet type */
  563|  21.1k|				+ 1;
  564|       |
  565|  21.1k|	writebuf = buf_new(encrypt_buf_size);
  566|  21.1k|	buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
  ------------------
  |  |   49|  21.1k|#define PACKET_PAYLOAD_OFF 5
  ------------------
  567|  21.1k|	buf_setpos(writebuf, PACKET_PAYLOAD_OFF);
  ------------------
  |  |   49|  21.1k|#define PACKET_PAYLOAD_OFF 5
  ------------------
  568|       |
  569|       |#ifndef DISABLE_ZLIB
  570|       |	/* compression */
  571|       |	if (is_compress_trans()) {
  572|       |		buf_compress(writebuf, ses.writepayload, ses.writepayload->len);
  573|       |	} else
  574|       |#endif
  575|  21.1k|	{
  576|  21.1k|		memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
  577|  21.1k|				buf_getptr(ses.writepayload, ses.writepayload->len),
  578|  21.1k|				ses.writepayload->len);
  579|  21.1k|		buf_incrwritepos(writebuf, ses.writepayload->len);
  580|  21.1k|	}
  581|       |
  582|       |	/* finished with payload */
  583|  21.1k|	buf_setpos(ses.writepayload, 0);
  584|  21.1k|	buf_setlen(ses.writepayload, 0);
  585|       |
  586|       |	/* length of padding - packet length excluding the packetlength uint32
  587|       |	 * field in aead mode must be a multiple of blocksize, with a minimum of
  588|       |	 * 4 bytes of padding */
  589|  21.1k|	len = writebuf->len;
  590|  21.1k|#if DROPBEAR_AEAD_MODE
  591|  21.1k|	if (ses.keys->trans.crypt_mode->aead_crypt) {
  ------------------
  |  Branch (591:6): [True: 0, False: 21.1k]
  ------------------
  592|      0|		len -= 4;
  593|      0|	}
  594|  21.1k|#endif
  595|  21.1k|	padlen = blocksize - len % blocksize;
  596|  21.1k|	if (padlen < 4) {
  ------------------
  |  Branch (596:6): [True: 0, False: 21.1k]
  ------------------
  597|      0|		padlen += blocksize;
  598|      0|	}
  599|       |	/* check for min packet length */
  600|  21.1k|	if (writebuf->len + padlen < MIN_PACKET_LEN) {
  ------------------
  |  |  241|  21.1k|#define MIN_PACKET_LEN 16
  ------------------
  |  Branch (600:6): [True: 0, False: 21.1k]
  ------------------
  601|      0|		padlen += blocksize;
  602|      0|	}
  603|       |
  604|  21.1k|	buf_setpos(writebuf, 0);
  605|       |	/* packet length excluding the packetlength uint32 */
  606|  21.1k|	buf_putint(writebuf, writebuf->len + padlen - 4);
  607|       |
  608|       |	/* padding len */
  609|  21.1k|	buf_putbyte(writebuf, padlen);
  610|       |	/* actual padding */
  611|  21.1k|	buf_setpos(writebuf, writebuf->len);
  612|  21.1k|	buf_incrlen(writebuf, padlen);
  613|  21.1k|	genrandom(buf_getptr(writebuf, padlen), padlen);
  614|       |
  615|  21.1k|#if DROPBEAR_AEAD_MODE
  616|  21.1k|	if (ses.keys->trans.crypt_mode->aead_crypt) {
  ------------------
  |  Branch (616:6): [True: 0, False: 21.1k]
  ------------------
  617|       |		/* do the actual encryption, in-place */
  618|      0|		buf_setpos(writebuf, 0);
  619|       |		/* encrypt it in-place*/
  620|      0|		len = writebuf->len;
  621|      0|		buf_incrlen(writebuf, mac_size);
  622|      0|		if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq,
  ------------------
  |  Branch (622:7): [True: 0, False: 0]
  ------------------
  623|      0|					buf_getptr(writebuf, len),
  624|      0|					buf_getwriteptr(writebuf, len + mac_size),
  625|      0|					len, mac_size,
  626|      0|					&ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) {
  ------------------
  |  |   68|      0|#define LTC_ENCRYPT 0
  ------------------
  627|      0|			dropbear_exit("Error encrypting");
  628|      0|		}
  629|      0|		buf_incrpos(writebuf, len + mac_size);
  630|      0|	} else
  631|  21.1k|#endif
  632|  21.1k|	{
  633|  21.1k|		make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
  634|       |
  635|       |		/* do the actual encryption, in-place */
  636|  21.1k|		buf_setpos(writebuf, 0);
  637|       |		/* encrypt it in-place*/
  638|  21.1k|		len = writebuf->len;
  639|  21.1k|		if (ses.keys->trans.crypt_mode->encrypt(
  ------------------
  |  Branch (639:7): [True: 0, False: 21.1k]
  ------------------
  640|  21.1k|					buf_getptr(writebuf, len),
  641|  21.1k|					buf_getwriteptr(writebuf, len),
  642|  21.1k|					len,
  643|  21.1k|					&ses.keys->trans.cipher_state) != CRYPT_OK) {
  644|      0|			dropbear_exit("Error encrypting");
  645|      0|		}
  646|  21.1k|		buf_incrpos(writebuf, len);
  647|       |
  648|       |		/* stick the MAC on it */
  649|  21.1k|		buf_putbytes(writebuf, mac_bytes, mac_size);
  650|  21.1k|	}
  651|       |
  652|       |	/* Update counts */
  653|  21.1k|	ses.kexstate.datatrans += writebuf->len;
  654|       |
  655|  21.1k|	writebuf_enqueue(writebuf);
  656|       |
  657|       |	/* Update counts */
  658|  21.1k|	ses.transseq++;
  659|       |
  660|  21.1k|	now = monotonic_now();
  661|  21.1k|	ses.last_packet_time_any_sent = now;
  662|       |	/* idle timeout shouldn't be affected by responses to keepalives.
  663|       |	send_msg_keepalive() itself also does tricks with 
  664|       |	ses.last_packet_idle_time - read that if modifying this code */
  665|  21.1k|	if (packet_type != SSH_MSG_REQUEST_FAILURE
  ------------------
  |  |   65|  42.2k|#define SSH_MSG_REQUEST_FAILURE                 82
  ------------------
  |  Branch (665:6): [True: 21.1k, False: 0]
  ------------------
  666|  21.1k|		&& packet_type != SSH_MSG_UNIMPLEMENTED
  ------------------
  |  |   31|  42.2k|#define SSH_MSG_UNIMPLEMENTED          3
  ------------------
  |  Branch (666:6): [True: 2.70k, False: 18.4k]
  ------------------
  667|  2.70k|		&& packet_type != SSH_MSG_IGNORE) {
  ------------------
  |  |   30|  2.70k|#define SSH_MSG_IGNORE                 2
  ------------------
  |  Branch (667:6): [True: 2.70k, False: 0]
  ------------------
  668|  2.70k|		ses.last_packet_time_idle = now;
  669|       |
  670|  2.70k|	}
  671|       |
  672|  21.1k|	TRACE2(("leave encrypt_packet()"))
  673|  21.1k|}
writebuf_enqueue:
  675|  23.8k|void writebuf_enqueue(buffer * writebuf) {
  676|       |	/* enqueue the packet for sending. It will get freed after transmission. */
  677|  23.8k|	buf_setpos(writebuf, 0);
  678|  23.8k|	enqueue(&ses.writequeue, (void*)writebuf);
  679|  23.8k|	ses.writequeue_len += writebuf->len;
  680|  23.8k|}
packet.c:read_packet_init:
  214|  87.8k|static int read_packet_init() {
  215|       |
  216|  87.8k|	unsigned int maxlen;
  217|  87.8k|	int slen;
  218|  87.8k|	unsigned int len, plen;
  219|  87.8k|	unsigned int blocksize;
  220|  87.8k|	unsigned int macsize;
  221|       |
  222|       |
  223|  87.8k|	blocksize = ses.keys->recv.algo_crypt->blocksize;
  224|  87.8k|	macsize = ses.keys->recv.algo_mac->hashsize;
  225|       |
  226|  87.8k|	if (ses.readbuf == NULL) {
  ------------------
  |  Branch (226:6): [True: 33.2k, False: 54.6k]
  ------------------
  227|       |		/* start of a new packet */
  228|  33.2k|		ses.readbuf = buf_new(INIT_READBUF);
  ------------------
  |  |   51|  33.2k|#define INIT_READBUF 128
  ------------------
  229|  33.2k|	}
  230|       |
  231|  87.8k|	maxlen = blocksize - ses.readbuf->pos;
  232|       |			
  233|       |	/* read the rest of the packet if possible */
  234|  87.8k|	slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
  ------------------
  |  |   55|  87.8k|#define read(fd, buf, count) wrapfd_read(fd, buf, count)
  ------------------
  235|  87.8k|			maxlen);
  236|  87.8k|	if (slen == 0) {
  ------------------
  |  Branch (236:6): [True: 1.12k, False: 86.7k]
  ------------------
  237|  1.12k|		ses.remoteclosed();
  238|  1.12k|	}
  239|  87.8k|	if (slen < 0) {
  ------------------
  |  Branch (239:6): [True: 87, False: 87.7k]
  ------------------
  240|     87|		if (errno == EINTR || errno == EAGAIN) {
  ------------------
  |  Branch (240:7): [True: 85, False: 2]
  |  Branch (240:25): [True: 0, False: 2]
  ------------------
  241|     85|			TRACE2(("leave read_packet_init: EINTR"))
  242|     85|			return DROPBEAR_FAILURE;
  ------------------
  |  |  112|     85|#define DROPBEAR_FAILURE -1
  ------------------
  243|     85|		}
  244|      2|		dropbear_exit("Error reading: %s", strerror(errno));
  245|     87|	}
  246|       |
  247|  87.7k|	buf_incrwritepos(ses.readbuf, slen);
  248|       |
  249|  87.7k|	if ((unsigned int)slen != maxlen) {
  ------------------
  |  Branch (249:6): [True: 54.5k, False: 33.2k]
  ------------------
  250|       |		/* don't have enough bytes to determine length, get next time */
  251|  54.5k|		return DROPBEAR_FAILURE;
  ------------------
  |  |  112|  54.5k|#define DROPBEAR_FAILURE -1
  ------------------
  252|  54.5k|	}
  253|       |
  254|       |	/* now we have the first block, need to get packet length, so we decrypt
  255|       |	 * the first block (only need first 4 bytes) */
  256|  33.2k|	buf_setpos(ses.readbuf, 0);
  257|  33.2k|#if DROPBEAR_AEAD_MODE
  258|  33.2k|	if (ses.keys->recv.crypt_mode->aead_crypt) {
  ------------------
  |  Branch (258:6): [True: 0, False: 33.2k]
  ------------------
  259|      0|		if (ses.keys->recv.crypt_mode->aead_getlength(ses.recvseq,
  ------------------
  |  Branch (259:7): [True: 0, False: 0]
  ------------------
  260|      0|					buf_getptr(ses.readbuf, blocksize), &plen,
  261|      0|					blocksize,
  262|      0|					&ses.keys->recv.cipher_state) != CRYPT_OK) {
  263|      0|			dropbear_exit("Error decrypting");
  264|      0|		}
  265|      0|		len = plen + 4 + macsize;
  266|      0|	} else
  267|  33.2k|#endif
  268|  33.2k|	{
  269|  33.2k|		if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), 
  ------------------
  |  Branch (269:7): [True: 0, False: 33.2k]
  ------------------
  270|  33.2k|					buf_getwriteptr(ses.readbuf, blocksize),
  271|  33.2k|					blocksize,
  272|  33.2k|					&ses.keys->recv.cipher_state) != CRYPT_OK) {
  273|      0|			dropbear_exit("Error decrypting");
  274|      0|		}
  275|  33.2k|		plen = buf_getint(ses.readbuf) + 4;
  276|  33.2k|		len = plen + macsize;
  277|  33.2k|	}
  278|       |
  279|  33.2k|	TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
  280|       |
  281|       |
  282|       |	/* check packet length */
  283|  33.2k|	if ((len > RECV_MAX_PACKET_LEN) ||
  ------------------
  |  |  243|  33.2k|#define RECV_MAX_PACKET_LEN (MAX(35000, ((RECV_MAX_PAYLOAD_LEN)+100)))
  ------------------
  |  Branch (283:6): [True: 1.15k, False: 32.0k]
  |  Branch (283:13): [True: 32.1k, Folded]
  ------------------
  284|  32.0k|		(plen < blocksize) ||
  ------------------
  |  Branch (284:3): [True: 1, False: 32.0k]
  ------------------
  285|  32.0k|		(plen % blocksize != 0)) {
  ------------------
  |  Branch (285:3): [True: 19, False: 32.0k]
  ------------------
  286|     49|		dropbear_exit("Integrity error (bad packet size %u)", len);
  287|     49|	}
  288|       |
  289|  33.1k|	if (len > ses.readbuf->size) {
  ------------------
  |  Branch (289:6): [True: 2.69k, False: 30.4k]
  ------------------
  290|  2.69k|		ses.readbuf = buf_resize(ses.readbuf, len);		
  291|  2.69k|	}
  292|  33.1k|	buf_setlen(ses.readbuf, len);
  293|  33.1k|	buf_setpos(ses.readbuf, blocksize);
  294|  33.1k|	return DROPBEAR_SUCCESS;
  ------------------
  |  |  111|  33.1k|#define DROPBEAR_SUCCESS 0
  ------------------
  295|  33.2k|}
packet.c:checkmac:
  390|  31.9k|static int checkmac() {
  391|       |
  392|  31.9k|	unsigned char mac_bytes[MAX_MAC_LEN];
  393|  31.9k|	unsigned int mac_size, contents_len;
  394|       |	
  395|  31.9k|	mac_size = ses.keys->recv.algo_mac->hashsize;
  396|  31.9k|	contents_len = ses.readbuf->len - mac_size;
  397|       |
  398|  31.9k|	buf_setpos(ses.readbuf, 0);
  399|  31.9k|	make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes);
  400|       |
  401|  31.9k|#if DROPBEAR_FUZZ
  402|  31.9k|	if (fuzz.fuzzing) {
  ------------------
  |  Branch (402:6): [True: 31.9k, False: 0]
  ------------------
  403|       |	 	/* fail 1 in 2000 times to test error path. */
  404|  31.9k|		unsigned int value = 0;
  405|  31.9k|		if (mac_size > sizeof(value)) {
  ------------------
  |  Branch (405:7): [True: 0, False: 31.9k]
  ------------------
  406|      0|			memcpy(&value, mac_bytes, sizeof(value));
  407|      0|		}
  408|  31.9k|		if (value % 2000 == 99) {
  ------------------
  |  Branch (408:7): [True: 0, False: 31.9k]
  ------------------
  409|      0|			return DROPBEAR_FAILURE;
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  410|      0|		}
  411|  31.9k|		return DROPBEAR_SUCCESS;
  ------------------
  |  |  111|  31.9k|#define DROPBEAR_SUCCESS 0
  ------------------
  412|  31.9k|	}
  413|      0|#endif
  414|       |
  415|       |	/* compare the hash */
  416|      0|	buf_setpos(ses.readbuf, contents_len);
  417|      0|	if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
  ------------------
  |  Branch (417:6): [True: 0, False: 0]
  ------------------
  418|      0|		return DROPBEAR_FAILURE;
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  419|      0|	} else {
  420|      0|		return DROPBEAR_SUCCESS;
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  421|      0|	}
  422|      0|}
packet.c:packet_is_okay_kex:
  464|  21.8k|static int packet_is_okay_kex(unsigned char type) {
  465|  21.8k|	if (type >= SSH_MSG_USERAUTH_REQUEST) {
  ------------------
  |  |   42|  21.8k|#define SSH_MSG_USERAUTH_REQUEST            50
  ------------------
  |  Branch (465:6): [True: 2.88k, False: 19.0k]
  ------------------
  466|  2.88k|		return 0;
  467|  2.88k|	}
  468|  19.0k|	if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
  ------------------
  |  |   33|  38.0k|#define SSH_MSG_SERVICE_REQUEST        5
  ------------------
              	if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
  ------------------
  |  |   34|  18.4k|#define SSH_MSG_SERVICE_ACCEPT         6
  ------------------
  |  Branch (468:6): [True: 591, False: 18.4k]
  |  Branch (468:41): [True: 0, False: 18.4k]
  ------------------
  469|    591|		return 0;
  470|    591|	}
  471|  18.4k|	if (type == SSH_MSG_KEXINIT) {
  ------------------
  |  |   36|  18.4k|#define SSH_MSG_KEXINIT                20
  ------------------
  |  Branch (471:6): [True: 0, False: 18.4k]
  ------------------
  472|       |		/* XXX should this die horribly if !dataallowed ?? */
  473|      0|		return 0;
  474|      0|	}
  475|  18.4k|	return 1;
  476|  18.4k|}
packet.c:enqueue_reply_packet:
  478|  3.47k|static void enqueue_reply_packet() {
  479|  3.47k|	struct packetlist * new_item = NULL;
  480|  3.47k|	new_item = m_malloc(sizeof(struct packetlist));
  481|  3.47k|	new_item->next = NULL;
  482|       |	
  483|  3.47k|	new_item->payload = buf_newcopy(ses.writepayload);
  484|  3.47k|	buf_setpos(ses.writepayload, 0);
  485|  3.47k|	buf_setlen(ses.writepayload, 0);
  486|       |	
  487|  3.47k|	if (ses.reply_queue_tail) {
  ------------------
  |  Branch (487:6): [True: 2.64k, False: 825]
  ------------------
  488|  2.64k|		ses.reply_queue_tail->next = new_item;
  489|  2.64k|	} else {
  490|    825|		ses.reply_queue_head = new_item;
  491|    825|	}
  492|  3.47k|	ses.reply_queue_tail = new_item;
  493|  3.47k|}
packet.c:make_mac:
  687|  53.0k|		unsigned char *output_mac) {
  688|  53.0k|	unsigned char seqbuf[4];
  689|  53.0k|	unsigned long bufsize;
  690|  53.0k|	hmac_state hmac;
  691|       |
  692|  53.0k|	if (key_state->algo_mac->hashsize > 0) {
  ------------------
  |  Branch (692:6): [True: 0, False: 53.0k]
  ------------------
  693|       |		/* calculate the mac */
  694|      0|		if (hmac_init(&hmac, 
  ------------------
  |  Branch (694:7): [True: 0, False: 0]
  ------------------
  695|      0|					key_state->hash_index,
  696|      0|					key_state->mackey,
  697|      0|					key_state->algo_mac->keysize) != CRYPT_OK) {
  698|      0|			dropbear_exit("HMAC error");
  699|      0|		}
  700|       |	
  701|       |		/* sequence number */
  702|      0|		STORE32H(seqno, seqbuf);
  ------------------
  |  |   62|      0|#define STORE32H(x, y)                          \
  |  |   63|      0|do { ulong32 __t = __builtin_bswap32 ((x));     \
  |  |   64|      0|      XMEMCPY ((y), &__t, 4); } while(0)
  |  |  ------------------
  |  |  |  |   39|      0|#define XMEMCPY  memcpy
  |  |  ------------------
  |  |  |  Branch (64:39): [Folded, False: 0]
  |  |  ------------------
  ------------------
  703|      0|		if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
  ------------------
  |  Branch (703:7): [True: 0, False: 0]
  ------------------
  704|      0|			dropbear_exit("HMAC error");
  705|      0|		}
  706|       |	
  707|       |		/* the actual contents */
  708|      0|		buf_setpos(clear_buf, 0);
  709|      0|		if (hmac_process(&hmac, 
  ------------------
  |  Branch (709:7): [True: 0, False: 0]
  ------------------
  710|      0|					buf_getptr(clear_buf, clear_len),
  711|      0|					clear_len) != CRYPT_OK) {
  712|      0|			dropbear_exit("HMAC error");
  713|      0|		}
  714|       |	
  715|      0|		bufsize = MAX_MAC_LEN;
  ------------------
  |  |  147|      0|#define MAX_MAC_LEN 32
  ------------------
  716|      0|		if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
  ------------------
  |  Branch (716:7): [True: 0, False: 0]
  ------------------
  717|      0|			dropbear_exit("HMAC error");
  718|      0|		}
  719|      0|	}
  720|  53.0k|	TRACE2(("leave writemac"))
  721|  53.0k|}

process_packet:
   43|  31.9k|void process_packet() {
   44|       |
   45|  31.9k|	unsigned char type;
   46|  31.9k|	unsigned int i;
   47|  31.9k|	unsigned int first_strict_kex = ses.kexstate.strict_kex && !ses.kexstate.recvfirstnewkeys;
  ------------------
  |  Branch (47:34): [True: 0, False: 31.9k]
  |  Branch (47:61): [True: 0, False: 0]
  ------------------
   48|  31.9k|	time_t now;
   49|       |
   50|  31.9k|	TRACE2(("enter process_packet"))
   51|       |
   52|  31.9k|	type = buf_getbyte(ses.payload);
   53|  31.9k|	TRACE(("process_packet: packet type = %d,  len %d", type, ses.payload->len))
   54|       |
   55|  31.9k|	now = monotonic_now();
   56|  31.9k|	ses.last_packet_time_keepalive_recv = now;
   57|       |
   58|       |
   59|  31.9k|	if (type == SSH_MSG_DISCONNECT) {
  ------------------
  |  |   29|  31.9k|#define SSH_MSG_DISCONNECT             1
  ------------------
  |  Branch (59:6): [True: 3, False: 31.9k]
  ------------------
   60|       |		/* Allowed at any time */
   61|      3|		dropbear_close("Disconnect received");
   62|      3|	}
   63|       |
   64|       |	/* These packets may be received at any time,
   65|       |	   except during first kex with strict kex */
   66|  31.9k|	if (!first_strict_kex) {
  ------------------
  |  Branch (66:6): [True: 31.9k, False: 3]
  ------------------
   67|  31.9k|		switch(type) {
  ------------------
  |  Branch (67:10): [True: 473, False: 31.4k]
  ------------------
   68|    160|			case SSH_MSG_IGNORE:
  ------------------
  |  |   30|    160|#define SSH_MSG_IGNORE                 2
  ------------------
  |  Branch (68:4): [True: 160, False: 31.7k]
  ------------------
   69|    160|				goto out;
   70|    190|			case SSH_MSG_DEBUG:
  ------------------
  |  |   32|    190|#define SSH_MSG_DEBUG                  4
  ------------------
  |  Branch (70:4): [True: 190, False: 31.7k]
  ------------------
   71|    190|				goto out;
   72|    123|			case SSH_MSG_UNIMPLEMENTED:
  ------------------
  |  |   31|    123|#define SSH_MSG_UNIMPLEMENTED          3
  ------------------
  |  Branch (72:4): [True: 123, False: 31.8k]
  ------------------
   73|    123|				TRACE(("SSH_MSG_UNIMPLEMENTED"))
   74|    123|				goto out;
   75|  31.9k|		}
   76|  31.9k|	}
   77|       |
   78|       |	/* Ignore these packet types so that keepalives don't interfere with
   79|       |	idle detection. This is slightly incorrect since a tcp forwarded
   80|       |	global request with failure won't trigger the idle timeout,
   81|       |	but that's probably acceptable */
   82|  31.4k|	if (!(type == SSH_MSG_GLOBAL_REQUEST 
  ------------------
  |  |   63|  62.9k|#define SSH_MSG_GLOBAL_REQUEST                  80
  ------------------
  |  Branch (82:8): [True: 922, False: 30.5k]
  ------------------
   83|  30.5k|		|| type == SSH_MSG_REQUEST_FAILURE
  ------------------
  |  |   65|  62.0k|#define SSH_MSG_REQUEST_FAILURE                 82
  ------------------
  |  Branch (83:6): [True: 196, False: 30.3k]
  ------------------
   84|  30.3k|		|| type == SSH_MSG_CHANNEL_FAILURE)) {
  ------------------
  |  |   76|  30.3k|#define SSH_MSG_CHANNEL_FAILURE                 100
  ------------------
  |  Branch (84:6): [True: 194, False: 30.1k]
  ------------------
   85|  30.1k|		ses.last_packet_time_idle = now;
   86|  30.1k|	}
   87|       |
   88|       |	/* This applies for KEX, where the spec says the next packet MUST be
   89|       |	 * NEWKEYS */
   90|  31.4k|	if (ses.requirenext != 0) {
  ------------------
  |  Branch (90:6): [True: 21.2k, False: 10.2k]
  ------------------
   91|  21.2k|		if (ses.requirenext == type)
  ------------------
  |  Branch (91:7): [True: 3.64k, False: 17.5k]
  ------------------
   92|  3.64k|		{
   93|       |			/* Got what we expected */
   94|  3.64k|			TRACE(("got expected packet %d during kexinit", type))
   95|  3.64k|		}
   96|  17.5k|		else
   97|  17.5k|		{
   98|       |			/* RFC4253 7.1 - various messages are allowed at this point.
   99|       |			The only ones we know about have already been handled though,
  100|       |			so just return "unimplemented" */
  101|  17.5k|			if (type >= 1 && type <= 49
  ------------------
  |  Branch (101:8): [True: 17.5k, False: 15]
  |  Branch (101:21): [True: 17.5k, False: 31]
  ------------------
  102|  17.5k|				&& type != SSH_MSG_SERVICE_REQUEST
  ------------------
  |  |   33|  35.1k|#define SSH_MSG_SERVICE_REQUEST        5
  ------------------
  |  Branch (102:8): [True: 17.5k, False: 1]
  ------------------
  103|  17.5k|				&& type != SSH_MSG_SERVICE_ACCEPT
  ------------------
  |  |   34|  35.1k|#define SSH_MSG_SERVICE_ACCEPT         6
  ------------------
  |  Branch (103:8): [True: 17.5k, False: 1]
  ------------------
  104|  17.5k|				&& type != SSH_MSG_KEXINIT
  ------------------
  |  |   36|  35.1k|#define SSH_MSG_KEXINIT                20
  ------------------
  |  Branch (104:8): [True: 17.5k, False: 1]
  ------------------
  105|  17.5k|				&& !first_strict_kex)
  ------------------
  |  Branch (105:8): [True: 17.5k, False: 0]
  ------------------
  106|  17.5k|			{
  107|  17.5k|				TRACE(("unknown allowed packet during kexinit"))
  108|  17.5k|				recv_unimplemented();
  109|  17.5k|				goto out;
  110|  17.5k|			}
  111|     49|			else
  112|     49|			{
  113|     49|				TRACE(("disallowed packet during kexinit"))
  114|     49|				dropbear_exit("Unexpected packet type %d, expected %d", type,
  115|     49|						ses.requirenext);
  116|     49|			}
  117|  17.5k|		}
  118|  21.2k|	}
  119|       |
  120|       |	/* Check if we should ignore this packet. Used currently only for
  121|       |	 * KEX code, with first_kex_packet_follows */
  122|  13.8k|	if (ses.ignorenext) {
  ------------------
  |  Branch (122:6): [True: 2, False: 13.8k]
  ------------------
  123|      2|		TRACE(("Ignoring packet, type = %d", type))
  124|      2|		ses.ignorenext = 0;
  125|      2|		goto out;
  126|      2|	}
  127|       |
  128|       |	/* Only clear the flag after we have checked ignorenext */
  129|  13.8k|	if (ses.requirenext != 0 && ses.requirenext == type)
  ------------------
  |  Branch (129:6): [True: 3.64k, False: 10.2k]
  |  Branch (129:30): [True: 3.64k, False: 0]
  ------------------
  130|  3.64k|	{
  131|  3.64k|		ses.requirenext = 0;
  132|  3.64k|	}
  133|       |
  134|       |
  135|       |	/* Kindly the protocol authors gave all the preauth packets type values
  136|       |	 * less-than-or-equal-to 60 ( == MAX_UNAUTH_PACKET_TYPE ).
  137|       |	 * NOTE: if the protocol changes and new types are added, revisit this 
  138|       |	 * assumption */
  139|  13.8k|	if ( !ses.authstate.authdone && type > MAX_UNAUTH_PACKET_TYPE ) {
  ------------------
  |  |   38|  8.41k|#define MAX_UNAUTH_PACKET_TYPE SSH_MSG_USERAUTH_PK_OK
  |  |  ------------------
  |  |  |  |   52|  8.41k|#define SSH_MSG_USERAUTH_PK_OK				60
  |  |  ------------------
  ------------------
  |  Branch (139:7): [True: 8.41k, False: 5.45k]
  |  Branch (139:34): [True: 4, False: 8.40k]
  ------------------
  140|      4|		dropbear_exit("Received message %d before userauth", type);
  141|      4|	}
  142|       |
  143|   159k|	for (i = 0; ; i++) {
  144|   159k|		if (ses.packettypes[i].type == 0) {
  ------------------
  |  Branch (144:7): [True: 877, False: 158k]
  ------------------
  145|       |			/* end of list */
  146|    877|			break;
  147|    877|		}
  148|       |
  149|   158k|		if (ses.packettypes[i].type == type) {
  ------------------
  |  Branch (149:7): [True: 12.9k, False: 145k]
  ------------------
  150|  12.9k|			ses.packettypes[i].handler();
  151|  12.9k|			goto out;
  152|  12.9k|		}
  153|   158k|	}
  154|       |
  155|       |	
  156|       |	/* TODO do something more here? */
  157|    880|	TRACE(("preauth unknown packet"))
  158|    880|	recv_unimplemented();
  159|       |
  160|  30.7k|out:
  161|  30.7k|	ses.lastpacket = type;
  162|  30.7k|	buf_free(ses.payload);
  163|  30.7k|	ses.payload = NULL;
  164|       |
  165|  30.7k|	TRACE2(("leave process_packet"))
  166|  30.7k|}
process-packet.c:recv_unimplemented:
  174|  18.4k|static void recv_unimplemented() {
  175|       |
  176|  18.4k|	CHECKCLEARTOWRITE();
  177|       |
  178|  18.4k|	buf_putbyte(ses.writepayload, SSH_MSG_UNIMPLEMENTED);
  ------------------
  |  |   31|  18.4k|#define SSH_MSG_UNIMPLEMENTED          3
  ------------------
  179|       |	/* the decryption routine increments the sequence number, we must
  180|       |	 * decrement */
  181|  18.4k|	buf_putint(ses.writepayload, ses.recvseq - 1);
  182|       |
  183|  18.4k|	encrypt_packet();
  184|  18.4k|}

initqueue:
   29|  2.70k|void initqueue(struct Queue* queue) {
   30|       |
   31|  2.70k|	queue->head = NULL;
   32|       |	queue->tail = NULL;
   33|  2.70k|	queue->count = 0;
   34|  2.70k|}
isempty:
   36|   357k|int isempty(const struct Queue* queue) {
   37|       |
   38|       |	return (queue->head == NULL);
   39|   357k|}
dequeue:
   41|  23.8k|void* dequeue(struct Queue* queue) {
   42|       |
   43|  23.8k|	void* ret;
   44|  23.8k|	struct Link* oldhead;
   45|  23.8k|	dropbear_assert(!isempty(queue));
  ------------------
  |  |   84|  23.8k|#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
  |  |  ------------------
  |  |  |  Branch (84:37): [True: 0, False: 23.8k]
  |  |  |  Branch (84:93): [Folded, False: 23.8k]
  |  |  ------------------
  ------------------
   46|       |	
   47|  23.8k|	ret = queue->head->item;
   48|  23.8k|	oldhead = queue->head;
   49|       |	
   50|  23.8k|	if (oldhead->link != NULL) {
  ------------------
  |  Branch (50:6): [True: 2.70k, False: 21.1k]
  ------------------
   51|  2.70k|		queue->head = oldhead->link;
   52|  21.1k|	} else {
   53|  21.1k|		queue->head = NULL;
   54|  21.1k|		queue->tail = NULL;
   55|  21.1k|		TRACE(("empty queue dequeing"))
   56|  21.1k|	}
   57|       |
   58|       |	m_free(oldhead);
  ------------------
  |  |   24|  23.8k|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 23.8k]
  |  |  ------------------
  ------------------
   59|  23.8k|	queue->count--;
   60|  23.8k|	return ret;
   61|  23.8k|}
examine:
   63|  23.8k|void *examine(const struct Queue* queue) {
   64|       |
   65|  23.8k|	dropbear_assert(!isempty(queue));
  ------------------
  |  |   84|  23.8k|#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
  |  |  ------------------
  |  |  |  Branch (84:37): [True: 0, False: 23.8k]
  |  |  |  Branch (84:93): [Folded, False: 23.8k]
  |  |  ------------------
  ------------------
   66|  23.8k|	return queue->head->item;
   67|  23.8k|}
enqueue:
   69|  23.8k|void enqueue(struct Queue* queue, void* item) {
   70|       |
   71|  23.8k|	struct Link* newlink;
   72|       |
   73|  23.8k|	newlink = (struct Link*)m_malloc(sizeof(struct Link));
   74|       |
   75|  23.8k|	newlink->item = item;
   76|  23.8k|	newlink->link = NULL;
   77|       |
   78|  23.8k|	if (queue->tail != NULL) {
  ------------------
  |  Branch (78:6): [True: 2.70k, False: 21.1k]
  ------------------
   79|  2.70k|		queue->tail->link = newlink;
   80|  2.70k|	}
   81|  23.8k|	queue->tail = newlink;
   82|       |
   83|  23.8k|	if (queue->head == NULL) {
  ------------------
  |  Branch (83:6): [True: 21.1k, False: 2.70k]
  ------------------
   84|  21.1k|		queue->head = newlink;
   85|  21.1k|	}
   86|  23.8k|	queue->count++;
   87|  23.8k|}

rsa_key_free:
  143|      2|void rsa_key_free(dropbear_rsa_key *key) {
  144|       |
  145|      2|	TRACE2(("enter rsa_key_free"))
  146|       |
  147|      2|	if (key == NULL) {
  ------------------
  |  Branch (147:6): [True: 2, False: 0]
  ------------------
  148|      2|		TRACE2(("leave rsa_key_free: key == NULL"))
  149|      2|		return;
  150|      2|	}
  151|      0|	m_mp_free_multi(&key->d, &key->e, &key->p, &key->q, &key->n, NULL);
  152|       |	m_free(key);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  153|      0|	TRACE2(("leave rsa_key_free"))
  154|      0|}

new_sign_key:
   62|      2|sign_key * new_sign_key() {
   63|       |
   64|      2|	sign_key * ret;
   65|       |
   66|      2|	ret = (sign_key*)m_malloc(sizeof(sign_key));
   67|      2|	ret->type = DROPBEAR_SIGNKEY_NONE;
   68|      2|	ret->source = SIGNKEY_SOURCE_INVALID;
   69|      2|	return ret;
   70|      2|}
signkey_type_from_name:
   86|      1|enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) {
   87|      1|	int i;
   88|      7|	for (i = 0; i < DROPBEAR_SIGNKEY_NUM_NAMED; i++) {
  ------------------
  |  Branch (88:14): [True: 7, False: 0]
  ------------------
   89|      7|		const char *fixed_name = signkey_names[i];
   90|      7|		if (namelen == strlen(fixed_name)
  ------------------
  |  Branch (90:7): [True: 1, False: 6]
  ------------------
   91|      1|			&& memcmp(fixed_name, name, namelen) == 0) {
  ------------------
  |  Branch (91:7): [True: 1, False: 0]
  ------------------
   92|       |
   93|      1|#if DROPBEAR_ECDSA
   94|       |			/* Some of the ECDSA key sizes are defined even if they're not compiled in */
   95|      1|			if (0
  ------------------
  |  Branch (95:8): [Folded, False: 1]
  ------------------
   96|       |#if !DROPBEAR_ECC_256
   97|       |				|| i == DROPBEAR_SIGNKEY_ECDSA_NISTP256
   98|       |#endif
   99|       |#if !DROPBEAR_ECC_384
  100|       |				|| i == DROPBEAR_SIGNKEY_ECDSA_NISTP384
  101|       |#endif
  102|       |#if !DROPBEAR_ECC_521
  103|       |				|| i == DROPBEAR_SIGNKEY_ECDSA_NISTP521
  104|       |#endif
  105|      1|				) {
  106|      0|				TRACE(("attempt to use ecdsa type %d not compiled in", i))
  107|      0|				return DROPBEAR_SIGNKEY_NONE;
  108|      0|			}
  109|      1|#endif
  110|       |
  111|      1|			return (enum signkey_type)i;
  112|      1|		}
  113|      7|	}
  114|       |
  115|      0|	TRACE(("signkey_type_from_name unexpected key type."))
  116|       |
  117|      0|	return DROPBEAR_SIGNKEY_NONE;
  118|      1|}
signkey_type_from_signature:
  173|  4.49k|enum signkey_type signkey_type_from_signature(enum signature_type sigtype) {
  174|  4.49k|#if DROPBEAR_RSA
  175|  4.49k|#if DROPBEAR_RSA_SHA256
  176|  4.49k|	if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) {
  ------------------
  |  Branch (176:6): [True: 1, False: 4.49k]
  ------------------
  177|      1|		return DROPBEAR_SIGNKEY_RSA;
  178|      1|	}
  179|  4.49k|#endif
  180|  4.49k|#if DROPBEAR_RSA_SHA1
  181|  4.49k|	if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA1) {
  ------------------
  |  Branch (181:6): [True: 7, False: 4.48k]
  ------------------
  182|      7|		return DROPBEAR_SIGNKEY_RSA;
  183|      7|	}
  184|  4.48k|#endif
  185|  4.48k|#endif /* DROPBEAR_RSA */
  186|  4.49k|	assert((int)sigtype < (int)DROPBEAR_SIGNKEY_NUM_NAMED);
  ------------------
  |  Branch (186:2): [True: 0, False: 4.48k]
  |  Branch (186:2): [True: 4.48k, False: 0]
  ------------------
  187|  4.48k|	return (enum signkey_type)sigtype;
  188|  4.48k|}
buf_get_priv_key:
  339|      1|int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
  340|       |
  341|      1|	char *ident;
  342|      1|	unsigned int len;
  343|      1|	enum signkey_type keytype;
  344|      1|	int ret = DROPBEAR_FAILURE;
  ------------------
  |  |  112|      1|#define DROPBEAR_FAILURE -1
  ------------------
  345|       |
  346|      1|	TRACE2(("enter buf_get_priv_key"))
  347|       |
  348|      1|	ident = buf_getstring(buf, &len);
  349|      1|	keytype = signkey_type_from_name(ident, len);
  350|      1|	m_free(ident);
  ------------------
  |  |   24|      1|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 1]
  |  |  ------------------
  ------------------
  351|       |
  352|      1|	if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
  ------------------
  |  Branch (352:6): [True: 0, False: 1]
  |  Branch (352:39): [True: 0, False: 0]
  ------------------
  353|      0|		TRACE(("wrong key type: %d %d", *type, keytype))
  354|      0|		return DROPBEAR_FAILURE;
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  355|      0|	}
  356|       |
  357|      1|	*type = keytype;
  358|       |
  359|       |	/* Rewind the buffer back before "ssh-rsa" etc */
  360|      1|	buf_decrpos(buf, len + 4);
  361|       |
  362|      1|#if DROPBEAR_DSS
  363|      1|	if (keytype == DROPBEAR_SIGNKEY_DSS) {
  ------------------
  |  Branch (363:6): [True: 0, False: 1]
  ------------------
  364|      0|		dss_key_free(key->dsskey);
  365|      0|		key->dsskey = m_malloc(sizeof(*key->dsskey));
  366|      0|		ret = buf_get_dss_priv_key(buf, key->dsskey);
  367|      0|		if (ret == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (367:7): [True: 0, False: 0]
  ------------------
  368|      0|			dss_key_free(key->dsskey);
  369|      0|			key->dsskey = NULL;
  370|      0|		}
  371|      0|	}
  372|      1|#endif
  373|      1|#if DROPBEAR_RSA
  374|      1|	if (keytype == DROPBEAR_SIGNKEY_RSA) {
  ------------------
  |  Branch (374:6): [True: 0, False: 1]
  ------------------
  375|      0|		rsa_key_free(key->rsakey);
  376|      0|		key->rsakey = m_malloc(sizeof(*key->rsakey));
  377|      0|		ret = buf_get_rsa_priv_key(buf, key->rsakey);
  378|      0|		if (ret == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      0|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (378:7): [True: 0, False: 0]
  ------------------
  379|      0|			rsa_key_free(key->rsakey);
  380|      0|			key->rsakey = NULL;
  381|      0|		}
  382|      0|	}
  383|      1|#endif
  384|      1|#if DROPBEAR_ECDSA
  385|      1|	if (signkey_is_ecdsa(keytype)) {
  ------------------
  |  Branch (385:6): [True: 0, False: 1]
  ------------------
  386|      0|		ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
  387|      0|		if (eck) {
  ------------------
  |  Branch (387:7): [True: 0, False: 0]
  ------------------
  388|      0|			if (*eck) {
  ------------------
  |  Branch (388:8): [True: 0, False: 0]
  ------------------
  389|      0|				ecc_free(*eck);
  390|      0|				m_free(*eck);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  391|      0|				*eck = NULL;
  392|      0|			}
  393|      0|			*eck = buf_get_ecdsa_priv_key(buf);
  394|      0|			if (*eck) {
  ------------------
  |  Branch (394:8): [True: 0, False: 0]
  ------------------
  395|      0|				ret = DROPBEAR_SUCCESS;
  ------------------
  |  |  111|      0|#define DROPBEAR_SUCCESS 0
  ------------------
  396|      0|			}
  397|      0|		}
  398|      0|	}
  399|      1|#endif
  400|      1|#if DROPBEAR_ED25519
  401|      1|	if (keytype == DROPBEAR_SIGNKEY_ED25519) {
  ------------------
  |  Branch (401:6): [True: 1, False: 0]
  ------------------
  402|      1|		ed25519_key_free(key->ed25519key);
  403|      1|		key->ed25519key = m_malloc(sizeof(*key->ed25519key));
  404|      1|		ret = buf_get_ed25519_priv_key(buf, key->ed25519key);
  405|      1|		if (ret == DROPBEAR_FAILURE) {
  ------------------
  |  |  112|      1|#define DROPBEAR_FAILURE -1
  ------------------
  |  Branch (405:7): [True: 0, False: 1]
  ------------------
  406|      0|			m_free(key->ed25519key);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  407|      0|			key->ed25519key = NULL;
  408|      0|		}
  409|      1|	}
  410|      1|#endif
  411|       |
  412|      1|	TRACE2(("leave buf_get_priv_key"))
  413|       |
  414|      1|	return ret;
  415|       |	
  416|      1|}
sign_key_free:
  506|      2|void sign_key_free(sign_key *key) {
  507|       |
  508|      2|	TRACE2(("enter sign_key_free"))
  509|       |
  510|      2|#if DROPBEAR_DSS
  511|      2|	dss_key_free(key->dsskey);
  512|      2|	key->dsskey = NULL;
  513|      2|#endif
  514|      2|#if DROPBEAR_RSA
  515|      2|	rsa_key_free(key->rsakey);
  516|      2|	key->rsakey = NULL;
  517|      2|#endif
  518|      2|#if DROPBEAR_ECDSA
  519|      2|#if DROPBEAR_ECC_256
  520|      2|	if (key->ecckey256) {
  ------------------
  |  Branch (520:6): [True: 0, False: 2]
  ------------------
  521|      0|		ecc_free(key->ecckey256);
  522|      0|		m_free(key->ecckey256);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  523|      0|		key->ecckey256 = NULL;
  524|      0|	}
  525|      2|#endif
  526|      2|#if DROPBEAR_ECC_384
  527|      2|	if (key->ecckey384) {
  ------------------
  |  Branch (527:6): [True: 0, False: 2]
  ------------------
  528|      0|		ecc_free(key->ecckey384);
  529|      0|		m_free(key->ecckey384);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  530|      0|		key->ecckey384 = NULL;
  531|      0|	}
  532|      2|#endif
  533|      2|#if DROPBEAR_ECC_521
  534|      2|	if (key->ecckey521) {
  ------------------
  |  Branch (534:6): [True: 0, False: 2]
  ------------------
  535|      0|		ecc_free(key->ecckey521);
  536|      0|		m_free(key->ecckey521);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  537|      0|		key->ecckey521 = NULL;
  538|      0|	}
  539|      2|#endif
  540|      2|#endif
  541|      2|#if DROPBEAR_ED25519
  542|      2|	ed25519_key_free(key->ed25519key);
  543|      2|	key->ed25519key = NULL;
  544|      2|#endif
  545|       |
  546|      2|	m_free(key->filename);
  ------------------
  |  |   24|      2|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2]
  |  |  ------------------
  ------------------
  547|      2|#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
  548|      2|	if (key->sk_app) {
  ------------------
  |  Branch (548:6): [True: 0, False: 2]
  ------------------
  549|      0|		m_free(key->sk_app);
  ------------------
  |  |   24|      0|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 0]
  |  |  ------------------
  ------------------
  550|      0|	}
  551|      2|#endif
  552|       |
  553|       |	m_free(key);
  ------------------
  |  |   24|      2|#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
  |  |  ------------------
  |  |  |  Branch (24:61): [Folded, False: 2]
  |  |  ------------------
  ------------------
  554|      2|	TRACE2(("leave sign_key_free"))
  555|      2|}

