Remove local main() definition.
[dragonfly.git] / crypto / openssh / bufaux.c
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"
40 RCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $");
41 RCSID("$FreeBSD: src/crypto/openssh/bufaux.c,v 1.2.2.4 2002/07/03 22:11:41 des Exp $");
42 RCSID("$DragonFly: src/crypto/openssh/Attic/bufaux.c,v 1.2 2003/06/17 04:24:36 dillon Exp $");
43
44 #include <openssl/bn.h>
45 #include "bufaux.h"
46 #include "xmalloc.h"
47 #include "getput.h"
48 #include "log.h"
49
50 /*
51  * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
52  * by (bits+7)/8 bytes of binary data, msb first.
53  */
54 void
55 buffer_put_bignum(Buffer *buffer, BIGNUM *value)
56 {
57         int bits = BN_num_bits(value);
58         int bin_size = (bits + 7) / 8;
59         u_char *buf = xmalloc(bin_size);
60         int oi;
61         char msg[2];
62
63         /* Get the value of in binary */
64         oi = BN_bn2bin(value, buf);
65         if (oi != bin_size)
66                 fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
67                     oi, bin_size);
68
69         /* Store the number of bits in the buffer in two bytes, msb first. */
70         PUT_16BIT(msg, bits);
71         buffer_append(buffer, msg, 2);
72         /* Store the binary data. */
73         buffer_append(buffer, (char *)buf, oi);
74
75         memset(buf, 0, bin_size);
76         xfree(buf);
77 }
78
79 /*
80  * Retrieves an BIGNUM from the buffer.
81  */
82 void
83 buffer_get_bignum(Buffer *buffer, BIGNUM *value)
84 {
85         int bits, bytes;
86         u_char buf[2], *bin;
87
88         /* Get the number for bits. */
89         buffer_get(buffer, (char *) buf, 2);
90         bits = GET_16BIT(buf);
91         /* Compute the number of binary bytes that follow. */
92         bytes = (bits + 7) / 8;
93         if (bytes > 8 * 1024)
94                 fatal("buffer_get_bignum: cannot handle BN of size %d", bytes);
95         if (buffer_len(buffer) < bytes)
96                 fatal("buffer_get_bignum: input buffer too small");
97         bin = buffer_ptr(buffer);
98         BN_bin2bn(bin, bytes, value);
99         buffer_consume(buffer, bytes);
100 }
101
102 /*
103  * Stores an BIGNUM in the buffer in SSH2 format.
104  */
105 void
106 buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
107 {
108         int bytes = BN_num_bytes(value) + 1;
109         u_char *buf = xmalloc(bytes);
110         int oi;
111         int hasnohigh = 0;
112
113         buf[0] = '\0';
114         /* Get the value of in binary */
115         oi = BN_bn2bin(value, buf+1);
116         if (oi != bytes-1)
117                 fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
118                     oi, bytes);
119         hasnohigh = (buf[1] & 0x80) ? 0 : 1;
120         if (value->neg) {
121                 /**XXX should be two's-complement */
122                 int i, carry;
123                 u_char *uc = buf;
124                 log("negativ!");
125                 for (i = bytes-1, carry = 1; i>=0; i--) {
126                         uc[i] ^= 0xff;
127                         if (carry)
128                                 carry = !++uc[i];
129                 }
130         }
131         buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
132         memset(buf, 0, bytes);
133         xfree(buf);
134 }
135
136 /* XXX does not handle negative BNs */
137 void
138 buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
139 {
140         u_int len;
141         u_char *bin = buffer_get_string(buffer, &len);
142
143         if (len > 8 * 1024)
144                 fatal("buffer_get_bignum2: cannot handle BN of size %d", len);
145         BN_bin2bn(bin, len, value);
146         xfree(bin);
147 }
148 /*
149  * Returns integers from the buffer (msb first).
150  */
151
152 u_short
153 buffer_get_short(Buffer *buffer)
154 {
155         u_char buf[2];
156
157         buffer_get(buffer, (char *) buf, 2);
158         return GET_16BIT(buf);
159 }
160
161 u_int
162 buffer_get_int(Buffer *buffer)
163 {
164         u_char buf[4];
165
166         buffer_get(buffer, (char *) buf, 4);
167         return GET_32BIT(buf);
168 }
169
170 #ifdef HAVE_U_INT64_T
171 u_int64_t
172 buffer_get_int64(Buffer *buffer)
173 {
174         u_char buf[8];
175
176         buffer_get(buffer, (char *) buf, 8);
177         return GET_64BIT(buf);
178 }
179 #endif
180
181 /*
182  * Stores integers in the buffer, msb first.
183  */
184 void
185 buffer_put_short(Buffer *buffer, u_short value)
186 {
187         char buf[2];
188
189         PUT_16BIT(buf, value);
190         buffer_append(buffer, buf, 2);
191 }
192
193 void
194 buffer_put_int(Buffer *buffer, u_int value)
195 {
196         char buf[4];
197
198         PUT_32BIT(buf, value);
199         buffer_append(buffer, buf, 4);
200 }
201
202 #ifdef HAVE_U_INT64_T
203 void
204 buffer_put_int64(Buffer *buffer, u_int64_t value)
205 {
206         char buf[8];
207
208         PUT_64BIT(buf, value);
209         buffer_append(buffer, buf, 8);
210 }
211 #endif
212
213 /*
214  * Returns an arbitrary binary string from the buffer.  The string cannot
215  * be longer than 256k.  The returned value points to memory allocated
216  * with xmalloc; it is the responsibility of the calling function to free
217  * the data.  If length_ptr is non-NULL, the length of the returned data
218  * will be stored there.  A null character will be automatically appended
219  * to the returned string, and is not counted in length.
220  */
221 void *
222 buffer_get_string(Buffer *buffer, u_int *length_ptr)
223 {
224         u_char *value;
225         u_int len;
226
227         /* Get the length. */
228         len = buffer_get_int(buffer);
229         if (len > 256 * 1024)
230                 fatal("buffer_get_string: bad string length %d", len);
231         /* Allocate space for the string.  Add one byte for a null character. */
232         value = xmalloc(len + 1);
233         /* Get the string. */
234         buffer_get(buffer, value, len);
235         /* Append a null character to make processing easier. */
236         value[len] = 0;
237         /* Optionally return the length of the string. */
238         if (length_ptr)
239                 *length_ptr = len;
240         return value;
241 }
242
243 /*
244  * Stores and arbitrary binary string in the buffer.
245  */
246 void
247 buffer_put_string(Buffer *buffer, const void *buf, u_int len)
248 {
249         buffer_put_int(buffer, len);
250         buffer_append(buffer, buf, len);
251 }
252 void
253 buffer_put_cstring(Buffer *buffer, const char *s)
254 {
255         if (s == NULL)
256                 fatal("buffer_put_cstring: s == NULL");
257         buffer_put_string(buffer, s, strlen(s));
258 }
259
260 /*
261  * Returns a character from the buffer (0 - 255).
262  */
263 int
264 buffer_get_char(Buffer *buffer)
265 {
266         char ch;
267
268         buffer_get(buffer, &ch, 1);
269         return (u_char) ch;
270 }
271
272 /*
273  * Stores a character in the buffer.
274  */
275 void
276 buffer_put_char(Buffer *buffer, int value)
277 {
278         char ch = value;
279
280         buffer_append(buffer, &ch, 1);
281 }