bufaux.c revision 98684
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 * Auxiliary functions for storing and retrieving various data types to/from
6 * Buffers.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose.  Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 *
14 *
15 * SSH2 packet format added by Markus Friedl
16 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include "includes.h"
40RCSID("$OpenBSD: bufaux.c,v 1.25 2002/04/20 09:14:58 markus Exp $");
41RCSID("$FreeBSD: head/crypto/openssh/bufaux.c 98684 2002-06-23 16:09:08Z des $");
42
43#include <openssl/bn.h>
44#include "bufaux.h"
45#include "xmalloc.h"
46#include "getput.h"
47#include "log.h"
48
49/*
50 * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
51 * by (bits+7)/8 bytes of binary data, msb first.
52 */
53void
54buffer_put_bignum(Buffer *buffer, BIGNUM *value)
55{
56	int bits = BN_num_bits(value);
57	int bin_size = (bits + 7) / 8;
58	u_char *buf = xmalloc(bin_size);
59	int oi;
60	char msg[2];
61
62	/* Get the value of in binary */
63	oi = BN_bn2bin(value, buf);
64	if (oi != bin_size)
65		fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
66		    oi, bin_size);
67
68	/* Store the number of bits in the buffer in two bytes, msb first. */
69	PUT_16BIT(msg, bits);
70	buffer_append(buffer, msg, 2);
71	/* Store the binary data. */
72	buffer_append(buffer, (char *)buf, oi);
73
74	memset(buf, 0, bin_size);
75	xfree(buf);
76}
77
78/*
79 * Retrieves an BIGNUM from the buffer.
80 */
81void
82buffer_get_bignum(Buffer *buffer, BIGNUM *value)
83{
84	int bits, bytes;
85	u_char buf[2], *bin;
86
87	/* Get the number for bits. */
88	buffer_get(buffer, (char *) buf, 2);
89	bits = GET_16BIT(buf);
90	/* Compute the number of binary bytes that follow. */
91	bytes = (bits + 7) / 8;
92	if (buffer_len(buffer) < bytes)
93		fatal("buffer_get_bignum: input buffer too small");
94	bin = buffer_ptr(buffer);
95	BN_bin2bn(bin, bytes, value);
96	buffer_consume(buffer, bytes);
97}
98
99/*
100 * Stores an BIGNUM in the buffer in SSH2 format.
101 */
102void
103buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
104{
105	int bytes = BN_num_bytes(value) + 1;
106	u_char *buf = xmalloc(bytes);
107	int oi;
108	int hasnohigh = 0;
109	buf[0] = '\0';
110	/* Get the value of in binary */
111	oi = BN_bn2bin(value, buf+1);
112	if (oi != bytes-1)
113		fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
114		    oi, bytes);
115	hasnohigh = (buf[1] & 0x80) ? 0 : 1;
116	if (value->neg) {
117		/**XXX should be two's-complement */
118		int i, carry;
119		u_char *uc = buf;
120		log("negativ!");
121		for (i = bytes-1, carry = 1; i>=0; i--) {
122			uc[i] ^= 0xff;
123			if (carry)
124				carry = !++uc[i];
125		}
126	}
127	buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
128	memset(buf, 0, bytes);
129	xfree(buf);
130}
131
132void
133buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
134{
135	/**XXX should be two's-complement */
136	int len;
137	u_char *bin = buffer_get_string(buffer, (u_int *)&len);
138	BN_bin2bn(bin, len, value);
139	xfree(bin);
140}
141/*
142 * Returns integers from the buffer (msb first).
143 */
144
145u_short
146buffer_get_short(Buffer *buffer)
147{
148	u_char buf[2];
149	buffer_get(buffer, (char *) buf, 2);
150	return GET_16BIT(buf);
151}
152
153u_int
154buffer_get_int(Buffer *buffer)
155{
156	u_char buf[4];
157	buffer_get(buffer, (char *) buf, 4);
158	return GET_32BIT(buf);
159}
160
161u_int64_t
162buffer_get_int64(Buffer *buffer)
163{
164	u_char buf[8];
165	buffer_get(buffer, (char *) buf, 8);
166	return GET_64BIT(buf);
167}
168
169/*
170 * Stores integers in the buffer, msb first.
171 */
172void
173buffer_put_short(Buffer *buffer, u_short value)
174{
175	char buf[2];
176	PUT_16BIT(buf, value);
177	buffer_append(buffer, buf, 2);
178}
179
180void
181buffer_put_int(Buffer *buffer, u_int value)
182{
183	char buf[4];
184	PUT_32BIT(buf, value);
185	buffer_append(buffer, buf, 4);
186}
187
188void
189buffer_put_int64(Buffer *buffer, u_int64_t value)
190{
191	char buf[8];
192	PUT_64BIT(buf, value);
193	buffer_append(buffer, buf, 8);
194}
195
196/*
197 * Returns an arbitrary binary string from the buffer.  The string cannot
198 * be longer than 256k.  The returned value points to memory allocated
199 * with xmalloc; it is the responsibility of the calling function to free
200 * the data.  If length_ptr is non-NULL, the length of the returned data
201 * will be stored there.  A null character will be automatically appended
202 * to the returned string, and is not counted in length.
203 */
204void *
205buffer_get_string(Buffer *buffer, u_int *length_ptr)
206{
207	u_int len;
208	u_char *value;
209	/* Get the length. */
210	len = buffer_get_int(buffer);
211	if (len > 256 * 1024)
212		fatal("buffer_get_string: bad string length %d", len);
213	/* Allocate space for the string.  Add one byte for a null character. */
214	value = xmalloc(len + 1);
215	/* Get the string. */
216	buffer_get(buffer, value, len);
217	/* Append a null character to make processing easier. */
218	value[len] = 0;
219	/* Optionally return the length of the string. */
220	if (length_ptr)
221		*length_ptr = len;
222	return value;
223}
224
225/*
226 * Stores and arbitrary binary string in the buffer.
227 */
228void
229buffer_put_string(Buffer *buffer, const void *buf, u_int len)
230{
231	buffer_put_int(buffer, len);
232	buffer_append(buffer, buf, len);
233}
234void
235buffer_put_cstring(Buffer *buffer, const char *s)
236{
237	if (s == NULL)
238		fatal("buffer_put_cstring: s == NULL");
239	buffer_put_string(buffer, s, strlen(s));
240}
241
242/*
243 * Returns a character from the buffer (0 - 255).
244 */
245int
246buffer_get_char(Buffer *buffer)
247{
248	char ch;
249	buffer_get(buffer, &ch, 1);
250	return (u_char) ch;
251}
252
253/*
254 * Stores a character in the buffer.
255 */
256void
257buffer_put_char(Buffer *buffer, int value)
258{
259	char ch = value;
260	buffer_append(buffer, &ch, 1);
261}
262