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"
| 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.32 2004/02/23 15:12:46 markus Exp $"); 41RCSID("$FreeBSD: head/crypto/openssh/bufaux.c 126277 2004-02-26 10:52:33Z des $");
| 40RCSID("$OpenBSD: bufaux.c,v 1.35 2005/03/10 22:01:05 deraadt Exp $"); 41RCSID("$FreeBSD: head/crypto/openssh/bufaux.c 147005 2005-06-05 15:46:09Z 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 */
| 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, const BIGNUM *value)
| 53int 54buffer_put_bignum_ret(Buffer *buffer, const 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);
| 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",
| 64 if (oi != bin_size) { 65 error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
|
66 oi, bin_size);
| 66 oi, bin_size);
|
| 67 return (-1); 68 }
|
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);
| 69 70 /* Store the number of bits in the buffer in two bytes, msb first. */ 71 PUT_16BIT(msg, bits); 72 buffer_append(buffer, msg, 2); 73 /* Store the binary data. */ 74 buffer_append(buffer, (char *)buf, oi); 75 76 memset(buf, 0, bin_size); 77 xfree(buf);
|
| 78 79 return (0);
|
76} 77
| 80} 81
|
| 82void 83buffer_put_bignum(Buffer *buffer, const BIGNUM *value) 84{ 85 if (buffer_put_bignum_ret(buffer, value) == -1) 86 fatal("buffer_put_bignum: buffer error"); 87} 88
|
78/* 79 * Retrieves an BIGNUM from the buffer. 80 */
| 89/* 90 * Retrieves an BIGNUM from the buffer. 91 */
|
81void 82buffer_get_bignum(Buffer *buffer, BIGNUM *value)
| 92int 93buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
|
83{ 84 u_int bits, bytes; 85 u_char buf[2], *bin; 86 87 /* Get the number for bits. */
| 94{ 95 u_int bits, bytes; 96 u_char buf[2], *bin; 97 98 /* Get the number for bits. */
|
88 buffer_get(buffer, (char *) buf, 2);
| 99 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) { 100 error("buffer_get_bignum_ret: invalid length"); 101 return (-1); 102 }
|
89 bits = GET_16BIT(buf); 90 /* Compute the number of binary bytes that follow. */ 91 bytes = (bits + 7) / 8;
| 103 bits = GET_16BIT(buf); 104 /* Compute the number of binary bytes that follow. */ 105 bytes = (bits + 7) / 8;
|
92 if (bytes > 8 * 1024) 93 fatal("buffer_get_bignum: cannot handle BN of size %d", bytes); 94 if (buffer_len(buffer) < bytes) 95 fatal("buffer_get_bignum: input buffer too small");
| 106 if (bytes > 8 * 1024) { 107 error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes); 108 return (-1); 109 } 110 if (buffer_len(buffer) < bytes) { 111 error("buffer_get_bignum_ret: input buffer too small"); 112 return (-1); 113 }
|
96 bin = buffer_ptr(buffer); 97 BN_bin2bn(bin, bytes, value);
| 114 bin = buffer_ptr(buffer); 115 BN_bin2bn(bin, bytes, value);
|
98 buffer_consume(buffer, bytes);
| 116 if (buffer_consume_ret(buffer, bytes) == -1) { 117 error("buffer_get_bignum_ret: buffer_consume failed"); 118 return (-1); 119 } 120 return (0);
|
99} 100
| 121} 122
|
| 123void 124buffer_get_bignum(Buffer *buffer, BIGNUM *value) 125{ 126 if (buffer_get_bignum_ret(buffer, value) == -1) 127 fatal("buffer_get_bignum: buffer error"); 128} 129
|
101/* 102 * Stores an BIGNUM in the buffer in SSH2 format. 103 */
| 130/* 131 * Stores an BIGNUM in the buffer in SSH2 format. 132 */
|
104void 105buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
| 133int 134buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
|
106{ 107 u_int bytes; 108 u_char *buf; 109 int oi; 110 u_int hasnohigh = 0; 111 112 if (BN_is_zero(value)) { 113 buffer_put_int(buffer, 0);
| 135{ 136 u_int bytes; 137 u_char *buf; 138 int oi; 139 u_int hasnohigh = 0; 140 141 if (BN_is_zero(value)) { 142 buffer_put_int(buffer, 0);
|
114 return;
| 143 return 0;
|
115 }
| 144 }
|
116 if (value->neg) 117 fatal("buffer_put_bignum2: negative numbers not supported");
| 145 if (value->neg) { 146 error("buffer_put_bignum2_ret: negative numbers not supported"); 147 return (-1); 148 }
|
118 bytes = BN_num_bytes(value) + 1; /* extra padding byte */
| 149 bytes = BN_num_bytes(value) + 1; /* extra padding byte */
|
119 if (bytes < 2) 120 fatal("buffer_put_bignum2: BN too small");
| 150 if (bytes < 2) { 151 error("buffer_put_bignum2_ret: BN too small"); 152 return (-1); 153 }
|
121 buf = xmalloc(bytes);
| 154 buf = xmalloc(bytes);
|
122 buf[0] = '\0';
| 155 buf[0] = 0x00;
|
123 /* Get the value of in binary */ 124 oi = BN_bn2bin(value, buf+1);
| 156 /* Get the value of in binary */ 157 oi = BN_bn2bin(value, buf+1);
|
125 if (oi != bytes-1) 126 fatal("buffer_put_bignum2: BN_bn2bin() failed: "
| 158 if (oi != bytes-1) { 159 error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
|
127 "oi %d != bin_size %d", oi, bytes);
| 160 "oi %d != bin_size %d", oi, bytes);
|
| 161 xfree(buf); 162 return (-1); 163 }
|
128 hasnohigh = (buf[1] & 0x80) ? 0 : 1; 129 buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); 130 memset(buf, 0, bytes); 131 xfree(buf);
| 164 hasnohigh = (buf[1] & 0x80) ? 0 : 1; 165 buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); 166 memset(buf, 0, bytes); 167 xfree(buf);
|
| 168 return (0);
|
132} 133 134void
| 169} 170 171void
|
135buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
| 172buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
|
136{
| 173{
|
| 174 if (buffer_put_bignum2_ret(buffer, value) == -1) 175 fatal("buffer_put_bignum2: buffer error"); 176} 177 178int 179buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) 180{
|
137 u_int len;
| 181 u_int len;
|
138 u_char *bin = buffer_get_string(buffer, &len);
| 182 u_char *bin;
|
139
| 183
|
140 if (len > 0 && (bin[0] & 0x80)) 141 fatal("buffer_get_bignum2: negative numbers not supported"); 142 if (len > 8 * 1024) 143 fatal("buffer_get_bignum2: cannot handle BN of size %d", len);
| 184 if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) { 185 error("buffer_get_bignum2_ret: invalid bignum"); 186 return (-1); 187 } 188 189 if (len > 0 && (bin[0] & 0x80)) { 190 error("buffer_get_bignum2_ret: negative numbers not supported"); 191 return (-1); 192 } 193 if (len > 8 * 1024) { 194 error("buffer_get_bignum2_ret: cannot handle BN of size %d", len); 195 return (-1); 196 }
|
144 BN_bin2bn(bin, len, value); 145 xfree(bin);
| 197 BN_bin2bn(bin, len, value); 198 xfree(bin);
|
| 199 return (0);
|
146} 147
| 200} 201
|
| 202void 203buffer_get_bignum2(Buffer *buffer, BIGNUM *value) 204{ 205 if (buffer_get_bignum2_ret(buffer, value) == -1) 206 fatal("buffer_get_bignum2: buffer error"); 207} 208
|
148/* 149 * Returns integers from the buffer (msb first). 150 */ 151
| 209/* 210 * Returns integers from the buffer (msb first). 211 */ 212
|
| 213int 214buffer_get_short_ret(u_short *ret, Buffer *buffer) 215{ 216 u_char buf[2]; 217 218 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) 219 return (-1); 220 *ret = GET_16BIT(buf); 221 return (0); 222} 223
|
152u_short 153buffer_get_short(Buffer *buffer) 154{
| 224u_short 225buffer_get_short(Buffer *buffer) 226{
|
155 u_char buf[2];
| 227 u_short ret;
|
156
| 228
|
157 buffer_get(buffer, (char *) buf, 2); 158 return GET_16BIT(buf);
| 229 if (buffer_get_short_ret(&ret, buffer) == -1) 230 fatal("buffer_get_short: buffer error"); 231 232 return (ret);
|
159} 160
| 233} 234
|
| 235int 236buffer_get_int_ret(u_int *ret, Buffer *buffer) 237{ 238 u_char buf[4]; 239 240 if (buffer_get_ret(buffer, (char *) buf, 4) == -1) 241 return (-1); 242 *ret = GET_32BIT(buf); 243 return (0); 244} 245
|
161u_int 162buffer_get_int(Buffer *buffer) 163{
| 246u_int 247buffer_get_int(Buffer *buffer) 248{
|
164 u_char buf[4];
| 249 u_int ret;
|
165
| 250
|
166 buffer_get(buffer, (char *) buf, 4); 167 return GET_32BIT(buf);
| 251 if (buffer_get_int_ret(&ret, buffer) == -1) 252 fatal("buffer_get_int: buffer error"); 253 254 return (ret);
|
168} 169
| 255} 256
|
| 257int 258buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) 259{ 260 u_char buf[8]; 261 262 if (buffer_get_ret(buffer, (char *) buf, 8) == -1) 263 return (-1); 264 *ret = GET_64BIT(buf); 265 return (0); 266} 267
|
170u_int64_t 171buffer_get_int64(Buffer *buffer) 172{
| 268u_int64_t 269buffer_get_int64(Buffer *buffer) 270{
|
173 u_char buf[8];
| 271 u_int64_t ret;
|
174
| 272
|
175 buffer_get(buffer, (char *) buf, 8); 176 return GET_64BIT(buf);
| 273 if (buffer_get_int64_ret(&ret, buffer) == -1) 274 fatal("buffer_get_int: buffer error"); 275 276 return (ret);
|
177} 178 179/* 180 * Stores integers in the buffer, msb first. 181 */ 182void 183buffer_put_short(Buffer *buffer, u_short value) 184{ 185 char buf[2]; 186 187 PUT_16BIT(buf, value); 188 buffer_append(buffer, buf, 2); 189} 190 191void 192buffer_put_int(Buffer *buffer, u_int value) 193{ 194 char buf[4]; 195 196 PUT_32BIT(buf, value); 197 buffer_append(buffer, buf, 4); 198} 199 200void 201buffer_put_int64(Buffer *buffer, u_int64_t value) 202{ 203 char buf[8]; 204 205 PUT_64BIT(buf, value); 206 buffer_append(buffer, buf, 8); 207} 208 209/* 210 * Returns an arbitrary binary string from the buffer. The string cannot 211 * be longer than 256k. The returned value points to memory allocated 212 * with xmalloc; it is the responsibility of the calling function to free 213 * the data. If length_ptr is non-NULL, the length of the returned data 214 * will be stored there. A null character will be automatically appended 215 * to the returned string, and is not counted in length. 216 */ 217void *
| 277} 278 279/* 280 * Stores integers in the buffer, msb first. 281 */ 282void 283buffer_put_short(Buffer *buffer, u_short value) 284{ 285 char buf[2]; 286 287 PUT_16BIT(buf, value); 288 buffer_append(buffer, buf, 2); 289} 290 291void 292buffer_put_int(Buffer *buffer, u_int value) 293{ 294 char buf[4]; 295 296 PUT_32BIT(buf, value); 297 buffer_append(buffer, buf, 4); 298} 299 300void 301buffer_put_int64(Buffer *buffer, u_int64_t value) 302{ 303 char buf[8]; 304 305 PUT_64BIT(buf, value); 306 buffer_append(buffer, buf, 8); 307} 308 309/* 310 * Returns an arbitrary binary string from the buffer. The string cannot 311 * be longer than 256k. The returned value points to memory allocated 312 * with xmalloc; it is the responsibility of the calling function to free 313 * the data. If length_ptr is non-NULL, the length of the returned data 314 * will be stored there. A null character will be automatically appended 315 * to the returned string, and is not counted in length. 316 */ 317void *
|
218buffer_get_string(Buffer *buffer, u_int *length_ptr)
| 318buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
|
219{ 220 u_char *value; 221 u_int len; 222 223 /* Get the length. */ 224 len = buffer_get_int(buffer);
| 319{ 320 u_char *value; 321 u_int len; 322 323 /* Get the length. */ 324 len = buffer_get_int(buffer);
|
225 if (len > 256 * 1024) 226 fatal("buffer_get_string: bad string length %u", len);
| 325 if (len > 256 * 1024) { 326 error("buffer_get_string_ret: bad string length %u", len); 327 return (NULL); 328 }
|
227 /* Allocate space for the string. Add one byte for a null character. */ 228 value = xmalloc(len + 1); 229 /* Get the string. */
| 329 /* Allocate space for the string. Add one byte for a null character. */ 330 value = xmalloc(len + 1); 331 /* Get the string. */
|
230 buffer_get(buffer, value, len);
| 332 if (buffer_get_ret(buffer, value, len) == -1) { 333 error("buffer_get_string_ret: buffer_get failed"); 334 xfree(value); 335 return (NULL); 336 }
|
231 /* Append a null character to make processing easier. */ 232 value[len] = 0; 233 /* Optionally return the length of the string. */ 234 if (length_ptr) 235 *length_ptr = len;
| 337 /* Append a null character to make processing easier. */ 338 value[len] = 0; 339 /* Optionally return the length of the string. */ 340 if (length_ptr) 341 *length_ptr = len;
|
236 return value;
| 342 return (value);
|
237} 238
| 343} 344
|
| 345void * 346buffer_get_string(Buffer *buffer, u_int *length_ptr) 347{ 348 void *ret; 349 350 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) 351 fatal("buffer_get_string: buffer error"); 352 return (ret); 353} 354
|
239/* 240 * Stores and arbitrary binary string in the buffer. 241 */ 242void 243buffer_put_string(Buffer *buffer, const void *buf, u_int len) 244{ 245 buffer_put_int(buffer, len); 246 buffer_append(buffer, buf, len); 247} 248void 249buffer_put_cstring(Buffer *buffer, const char *s) 250{ 251 if (s == NULL) 252 fatal("buffer_put_cstring: s == NULL"); 253 buffer_put_string(buffer, s, strlen(s)); 254} 255 256/* 257 * Returns a character from the buffer (0 - 255). 258 */ 259int
| 355/* 356 * Stores and arbitrary binary string in the buffer. 357 */ 358void 359buffer_put_string(Buffer *buffer, const void *buf, u_int len) 360{ 361 buffer_put_int(buffer, len); 362 buffer_append(buffer, buf, len); 363} 364void 365buffer_put_cstring(Buffer *buffer, const char *s) 366{ 367 if (s == NULL) 368 fatal("buffer_put_cstring: s == NULL"); 369 buffer_put_string(buffer, s, strlen(s)); 370} 371 372/* 373 * Returns a character from the buffer (0 - 255). 374 */ 375int
|
| 376buffer_get_char_ret(char *ret, Buffer *buffer) 377{ 378 if (buffer_get_ret(buffer, ret, 1) == -1) { 379 error("buffer_get_char_ret: buffer_get_ret failed"); 380 return (-1); 381 } 382 return (0); 383} 384 385int
|
260buffer_get_char(Buffer *buffer) 261{ 262 char ch; 263
| 386buffer_get_char(Buffer *buffer) 387{ 388 char ch; 389
|
264 buffer_get(buffer, &ch, 1);
| 390 if (buffer_get_char_ret(&ch, buffer) == -1) 391 fatal("buffer_get_char: buffer error");
|
265 return (u_char) ch; 266} 267 268/* 269 * Stores a character in the buffer. 270 */ 271void 272buffer_put_char(Buffer *buffer, int value) 273{ 274 char ch = value; 275 276 buffer_append(buffer, &ch, 1); 277}
| 392 return (u_char) ch; 393} 394 395/* 396 * Stores a character in the buffer. 397 */ 398void 399buffer_put_char(Buffer *buffer, int value) 400{ 401 char ch = value; 402 403 buffer_append(buffer, &ch, 1); 404}
|