1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: roaming_common.c,v 1.13 2015/01/27 12:54:06 okan Exp $ */
2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2004-2009 AppGate Network Security AB
4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Permission to use, copy, modify, and distribute this software for any
6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * purpose with or without fee is hereby granted, provided that the above
7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * copyright notice and this permission notice appear in all copies.
8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h"
19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h>
21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/socket.h>
22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/uio.h>
23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <errno.h>
25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h>
26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h>
27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h>
28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "atomicio.h"
30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h"
31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "packet.h"
32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "xmalloc.h"
33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "cipher.h"
34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "buffer.h"
35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "roaming.h"
36d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "digest.h"
37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic size_t out_buf_size = 0;
39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic char *out_buf = NULL;
40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic size_t out_start;
41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic size_t out_last;
42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic u_int64_t write_bytes = 0;
44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic u_int64_t read_bytes = 0;
45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint roaming_enabled = 0;
47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint resume_in_progress = 0;
48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint
50d059297112922cabb0c674840589be8db821fd9aAdam Langleyget_snd_buf_size(void)
51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int fd = packet_get_connection_out();
53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int optval;
54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	socklen_t optvallen = sizeof(optval);
55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optvallen) != 0)
57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		optval = DEFAULT_ROAMBUF;
58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return optval;
59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint
62d059297112922cabb0c674840589be8db821fd9aAdam Langleyget_recv_buf_size(void)
63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int fd = packet_get_connection_in();
65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int optval;
66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	socklen_t optvallen = sizeof(optval);
67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &optval, &optvallen) != 0)
69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		optval = DEFAULT_ROAMBUF;
70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return optval;
71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid
74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanset_out_buffer_size(size_t size)
75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
76d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (size == 0 || size > MAX_ROAMBUF)
77d059297112922cabb0c674840589be8db821fd9aAdam Langley		fatal("%s: bad buffer size %lu", __func__, (u_long)size);
78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/*
79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	 * The buffer size can only be set once and the buffer will live
80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	 * as long as the session lives.
81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	 */
82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (out_buf == NULL) {
83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		out_buf_size = size;
84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		out_buf = xmalloc(size);
85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		out_start = 0;
86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		out_last = 0;
87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int64_t
91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_recv_bytes(void)
92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return read_bytes;
94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid
97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanadd_recv_bytes(u_int64_t num)
98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	read_bytes += num;
100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int64_t
103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanget_sent_bytes(void)
104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return write_bytes;
106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid
109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanroam_set_bytes(u_int64_t sent, u_int64_t recvd)
110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	read_bytes = recvd;
112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	write_bytes = sent;
113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void
116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanbuf_append(const char *buf, size_t count)
117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (count > out_buf_size) {
119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		buf += count - out_buf_size;
120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		count = out_buf_size;
121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (count < out_buf_size - out_last) {
123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		memcpy(out_buf + out_last, buf, count);
124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (out_start > out_last)
125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			out_start += count;
126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		out_last += count;
127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	} else {
128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		/* data will wrap */
129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		size_t chunk = out_buf_size - out_last;
130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		memcpy(out_buf + out_last, buf, chunk);
131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		memcpy(out_buf, buf + chunk, count - chunk);
132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		out_last = count - chunk;
133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		out_start = out_last + 1;
134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanssize_t
138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanroaming_write(int fd, const void *buf, size_t count, int *cont)
139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ssize_t ret;
141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ret = write(fd, buf, count);
143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (ret > 0 && !resume_in_progress) {
144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		write_bytes += ret;
145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (out_buf_size > 0)
146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			buf_append(buf, ret);
147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (out_buf_size > 0 &&
149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    (ret == 0 || (ret == -1 && errno == EPIPE))) {
150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (wait_for_roaming_reconnect() != 0) {
151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			ret = 0;
152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			*cont = 1;
153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		} else {
154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			ret = -1;
155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			errno = EAGAIN;
156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return ret;
159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanssize_t
162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanroaming_read(int fd, void *buf, size_t count, int *cont)
163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	ssize_t ret = read(fd, buf, count);
165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (ret > 0) {
166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (!resume_in_progress) {
167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			read_bytes += ret;
168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	} else if (out_buf_size > 0 &&
170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    (ret == 0 || (ret == -1 && (errno == ECONNRESET
171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    || errno == ECONNABORTED || errno == ETIMEDOUT
172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    || errno == EHOSTUNREACH)))) {
173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		debug("roaming_read failed for %d  ret=%ld  errno=%d",
174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    fd, (long)ret, errno);
175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		ret = 0;
176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (wait_for_roaming_reconnect() == 0)
177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			*cont = 1;
178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return ret;
180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansize_t
183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanroaming_atomicio(ssize_t(*f)(int, void*, size_t), int fd, void *buf,
184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman    size_t count)
185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	size_t ret = atomicio(f, fd, buf, count);
187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (f == vwrite && ret > 0 && !resume_in_progress) {
189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		write_bytes += ret;
190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	} else if (f == read && ret > 0 && !resume_in_progress) {
191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		read_bytes += ret;
192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return ret;
194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid
197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanresend_bytes(int fd, u_int64_t *offset)
198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	size_t available, needed;
200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (out_start < out_last)
202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		available = out_last - out_start;
203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	else
204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		available = out_buf_size;
205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	needed = write_bytes - *offset;
206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	debug3("resend_bytes: resend %lu bytes from %llu",
207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    (unsigned long)needed, (unsigned long long)*offset);
208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (needed > available)
209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		fatal("Needed to resend more data than in the cache");
210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (out_last < needed) {
211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		int chunkend = needed - out_last;
212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		atomicio(vwrite, fd, out_buf + out_buf_size - chunkend,
213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    chunkend);
214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		atomicio(vwrite, fd, out_buf, out_last);
215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	} else {
216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		atomicio(vwrite, fd, out_buf + (out_last - needed), needed);
217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Caclulate a new key after a reconnect
222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid
224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancalculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge)
225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
226d059297112922cabb0c674840589be8db821fd9aAdam Langley	u_char hash[SSH_DIGEST_MAX_LENGTH];
227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	Buffer b;
228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	buffer_init(&b);
230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	buffer_put_int64(&b, *key);
231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	buffer_put_int64(&b, cookie);
232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	buffer_put_int64(&b, challenge);
233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
234d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, hash, sizeof(hash)) != 0)
235d059297112922cabb0c674840589be8db821fd9aAdam Langley		fatal("%s: digest_buffer failed", __func__);
236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	buffer_clear(&b);
238d059297112922cabb0c674840589be8db821fd9aAdam Langley	buffer_append(&b, hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	*key = buffer_get_int64(&b);
240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	buffer_free(&b);
241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
242