bufaux.c revision 99063
1153761Swollman/*
2192886Sedwin * Author: Tatu Ylonen <ylo@cs.hut.fi>
3192886Sedwin * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4192886Sedwin *                    All rights reserved
564499Swollman * Auxiliary functions for storing and retrieving various data types to/from
62742Swollman * Buffers.
72742Swollman *
82742Swollman * As far as I am concerned, the code I have written for this software
92742Swollman * can be used freely for any purpose.  Any derived versions of this
10158421Swollman * software must be clearly marked as such, and if the derived work is
112742Swollman * incompatible with the protocol description in the RFC file, it must be
12158421Swollman * called by a name other than "ssh" or "Secure Shell".
13158421Swollman *
142742Swollman *
1586222Swollman * SSH2 packet format added by Markus Friedl
1620094Swollman * Copyright (c) 2000 Markus Friedl.  All rights reserved.
1720094Swollman *
1820094Swollman * Redistribution and use in source and binary forms, with or without
1920094Swollman * modification, are permitted provided that the following conditions
2020094Swollman * are met:
21158421Swollman * 1. Redistributions of source code must retain the above copyright
22158421Swollman *    notice, this list of conditions and the following disclaimer.
2320094Swollman * 2. Redistributions in binary form must reproduce the above copyright
2419878Swollman *    notice, this list of conditions and the following disclaimer in the
2519878Swollman *    documentation and/or other materials provided with the distribution.
2619878Swollman *
2719878Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2819878Swollman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2919878Swollman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3019878Swollman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3119878Swollman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3258787Sru * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3358787Sru * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3458787Sru * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3558787Sru * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3658787Sru * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3758787Sru */
3858787Sru
3958787Sru#include "includes.h"
4058787SruRCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $");
4158787SruRCSID("$FreeBSD: head/crypto/openssh/bufaux.c 99063 2002-06-29 11:48:59Z des $");
4258787Sru
4358787Sru#include <openssl/bn.h>
4458787Sru#include "bufaux.h"
4558787Sru#include "xmalloc.h"
4658787Sru#include "getput.h"
4758787Sru#include "log.h"
4858787Sru
4958787Sru/*
502742Swollman * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
512742Swollman * by (bits+7)/8 bytes of binary data, msb first.
522742Swollman */
532742Swollmanvoid
542742Swollmanbuffer_put_bignum(Buffer *buffer, BIGNUM *value)
552742Swollman{
562742Swollman	int bits = BN_num_bits(value);
5719878Swollman	int bin_size = (bits + 7) / 8;
582742Swollman	u_char *buf = xmalloc(bin_size);
592742Swollman	int oi;
602742Swollman	char msg[2];
6119878Swollman
622742Swollman	/* Get the value of in binary */
632742Swollman	oi = BN_bn2bin(value, buf);
64149514Swollman	if (oi != bin_size)
6521217Swollman		fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
669908Swollman		    oi, bin_size);
679908Swollman
682742Swollman	/* Store the number of bits in the buffer in two bytes, msb first. */
6919878Swollman	PUT_16BIT(msg, bits);
7019878Swollman	buffer_append(buffer, msg, 2);
7119878Swollman	/* Store the binary data. */
7219878Swollman	buffer_append(buffer, (char *)buf, oi);
7319878Swollman
7419878Swollman	memset(buf, 0, bin_size);
7519878Swollman	xfree(buf);
7619878Swollman}
7719878Swollman
7819878Swollman/*
7919878Swollman * Retrieves an BIGNUM from the buffer.
8019878Swollman */
8119878Swollmanvoid
8219878Swollmanbuffer_get_bignum(Buffer *buffer, BIGNUM *value)
8319878Swollman{
8419878Swollman	int bits, bytes;
8593799Swollman	u_char buf[2], *bin;
8658787Sru
8758787Sru	/* Get the number for bits. */
8819878Swollman	buffer_get(buffer, (char *) buf, 2);
8919878Swollman	bits = GET_16BIT(buf);
9019878Swollman	/* Compute the number of binary bytes that follow. */
919908Swollman	bytes = (bits + 7) / 8;
92149514Swollman	if (bytes > 8 * 1024)
939908Swollman		fatal("buffer_get_bignum: cannot handle BN of size %d", bytes);
949908Swollman	if (buffer_len(buffer) < bytes)
959908Swollman		fatal("buffer_get_bignum: input buffer too small");
9621217Swollman	bin = buffer_ptr(buffer);
9719878Swollman	BN_bin2bn(bin, bytes, value);
9819878Swollman	buffer_consume(buffer, bytes);
999908Swollman}
100149514Swollman
1019908Swollman/*
1029908Swollman * Stores an BIGNUM in the buffer in SSH2 format.
1039908Swollman */
1049908Swollmanvoid
10558787Srubuffer_put_bignum2(Buffer *buffer, BIGNUM *value)
10658787Sru{
10758787Sru	int bytes = BN_num_bytes(value) + 1;
10864499Swollman	u_char *buf = xmalloc(bytes);
10964499Swollman	int oi;
110175034Sedwin	int hasnohigh = 0;
111175034Sedwin
112175034Sedwin	buf[0] = '\0';
113175034Sedwin	/* Get the value of in binary */
114175034Sedwin	oi = BN_bn2bin(value, buf+1);
11558787Sru	if (oi != bytes-1)
11658787Sru		fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
11767578Swollman		    oi, bytes);
11858787Sru	hasnohigh = (buf[1] & 0x80) ? 0 : 1;
11958787Sru	if (value->neg) {
12058787Sru		/**XXX should be two's-complement */
121149514Swollman		int i, carry;
12264499Swollman		u_char *uc = buf;
12364499Swollman		log("negativ!");
12464499Swollman		for (i = bytes-1, carry = 1; i>=0; i--) {
12564499Swollman			uc[i] ^= 0xff;
12686222Swollman			if (carry)
12786222Swollman				carry = !++uc[i];
12886222Swollman		}
12986222Swollman	}
13086222Swollman	buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
13186222Swollman	memset(buf, 0, bytes);
13286222Swollman	xfree(buf);
13386222Swollman}
13486222Swollman
13586222Swollman/* XXX does not handle negative BNs */
13686222Swollmanvoid
13786222Swollmanbuffer_get_bignum2(Buffer *buffer, BIGNUM *value)
13886222Swollman{
13986222Swollman	u_int len;
14086222Swollman	u_char *bin = buffer_get_string(buffer, &len);
14186222Swollman
14286222Swollman	if (len > 8 * 1024)
14386222Swollman		fatal("buffer_get_bignum2: cannot handle BN of size %d", len);
14486222Swollman	BN_bin2bn(bin, len, value);
14586222Swollman	xfree(bin);
14686222Swollman}
14786222Swollman/*
14886222Swollman * Returns integers from the buffer (msb first).
149175034Sedwin */
150175034Sedwin
151175034Sedwinu_short
152175034Sedwinbuffer_get_short(Buffer *buffer)
153175034Sedwin{
154175034Sedwin	u_char buf[2];
155175034Sedwin
156175034Sedwin	buffer_get(buffer, (char *) buf, 2);
157175034Sedwin	return GET_16BIT(buf);
158175034Sedwin}
159175034Sedwin
160175034Sedwinu_int
161175034Sedwinbuffer_get_int(Buffer *buffer)
162175034Sedwin{
163175034Sedwin	u_char buf[4];
164175034Sedwin
165175034Sedwin	buffer_get(buffer, (char *) buf, 4);
166175034Sedwin	return GET_32BIT(buf);
167175034Sedwin}
168175034Sedwin
169183066Sedwin#ifdef HAVE_U_INT64_T
170183066Sedwinu_int64_t
171183066Sedwinbuffer_get_int64(Buffer *buffer)
172183066Sedwin{
173183066Sedwin	u_char buf[8];
174183066Sedwin
175183066Sedwin	buffer_get(buffer, (char *) buf, 8);
176183066Sedwin	return GET_64BIT(buf);
177183066Sedwin}
178183066Sedwin#endif
179183066Sedwin
180183066Sedwin/*
181183066Sedwin * Stores integers in the buffer, msb first.
182183864Sedwin */
183183864Sedwinvoid
184183864Sedwinbuffer_put_short(Buffer *buffer, u_short value)
185183864Sedwin{
186183864Sedwin	char buf[2];
187183864Sedwin
188183864Sedwin	PUT_16BIT(buf, value);
189183864Sedwin	buffer_append(buffer, buf, 2);
190183864Sedwin}
191183864Sedwin
192183864Sedwinvoid
193183864Sedwinbuffer_put_int(Buffer *buffer, u_int value)
194183864Sedwin{
195183864Sedwin	char buf[4];
196183864Sedwin
197183864Sedwin	PUT_32BIT(buf, value);
198184406Sedwin	buffer_append(buffer, buf, 4);
199184406Sedwin}
200184406Sedwin
201184406Sedwin#ifdef HAVE_U_INT64_T
202184406Sedwinvoid
203184406Sedwinbuffer_put_int64(Buffer *buffer, u_int64_t value)
204184406Sedwin{
205184406Sedwin	char buf[8];
206184406Sedwin
207184406Sedwin	PUT_64BIT(buf, value);
208184406Sedwin	buffer_append(buffer, buf, 8);
209184406Sedwin}
210184406Sedwin#endif
211184406Sedwin
212184406Sedwin/*
213184406Sedwin * Returns an arbitrary binary string from the buffer.  The string cannot
214184406Sedwin * be longer than 256k.  The returned value points to memory allocated
215184406Sedwin * with xmalloc; it is the responsibility of the calling function to free
216184406Sedwin * the data.  If length_ptr is non-NULL, the length of the returned data
217184406Sedwin * will be stored there.  A null character will be automatically appended
218175034Sedwin * to the returned string, and is not counted in length.
219175034Sedwin */
220183066Sedwinvoid *
221175034Sedwinbuffer_get_string(Buffer *buffer, u_int *length_ptr)
222136638Swollman{
223136638Swollman	u_char *value;
224136638Swollman	u_int len;
225136638Swollman
226136638Swollman	/* Get the length. */
227136638Swollman	len = buffer_get_int(buffer);
228136638Swollman	if (len > 256 * 1024)
22993799Swollman		fatal("buffer_get_string: bad string length %d", len);
230158421Swollman	/* Allocate space for the string.  Add one byte for a null character. */
23193799Swollman	value = xmalloc(len + 1);
232158421Swollman	/* Get the string. */
23393799Swollman	buffer_get(buffer, value, len);
23493799Swollman	/* Append a null character to make processing easier. */
235158421Swollman	value[len] = 0;
236136638Swollman	/* Optionally return the length of the string. */
237136638Swollman	if (length_ptr)
238136638Swollman		*length_ptr = len;
239136638Swollman	return value;
240136638Swollman}
241136638Swollman
242136638Swollman/*
243136638Swollman * Stores and arbitrary binary string in the buffer.
244136638Swollman */
245136638Swollmanvoid
246136638Swollmanbuffer_put_string(Buffer *buffer, const void *buf, u_int len)
247136638Swollman{
248136638Swollman	buffer_put_int(buffer, len);
249136638Swollman	buffer_append(buffer, buf, len);
250136638Swollman}
251136638Swollmanvoid
252136638Swollmanbuffer_put_cstring(Buffer *buffer, const char *s)
253136638Swollman{
254136638Swollman	if (s == NULL)
255136638Swollman		fatal("buffer_put_cstring: s == NULL");
256136638Swollman	buffer_put_string(buffer, s, strlen(s));
257136638Swollman}
258136638Swollman
259136638Swollman/*
260136638Swollman * Returns a character from the buffer (0 - 255).
261136638Swollman */
262136638Swollmanint
263136638Swollmanbuffer_get_char(Buffer *buffer)
264136638Swollman{
265136638Swollman	char ch;
266136638Swollman
267136638Swollman	buffer_get(buffer, &ch, 1);
268136638Swollman	return (u_char) ch;
269136638Swollman}
270136638Swollman
271136638Swollman/*
272136638Swollman * Stores a character in the buffer.
273136638Swollman */
274136638Swollmanvoid
275136638Swollmanbuffer_put_char(Buffer *buffer, int value)
276136638Swollman{
277136638Swollman	char ch = value;
278136638Swollman
279136638Swollman	buffer_append(buffer, &ch, 1);
280136638Swollman}
28193799Swollman