bufaux.c revision 98941
11556Srgrimes/* 21556Srgrimes * Author: Tatu Ylonen <ylo@cs.hut.fi> 31556Srgrimes * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 41556Srgrimes * All rights reserved 51556Srgrimes * Auxiliary functions for storing and retrieving various data types to/from 61556Srgrimes * Buffers. 71556Srgrimes * 81556Srgrimes * As far as I am concerned, the code I have written for this software 91556Srgrimes * can be used freely for any purpose. Any derived versions of this 101556Srgrimes * software must be clearly marked as such, and if the derived work is 111556Srgrimes * incompatible with the protocol description in the RFC file, it must be 121556Srgrimes * called by a name other than "ssh" or "Secure Shell". 131556Srgrimes * 141556Srgrimes * 151556Srgrimes * SSH2 packet format added by Markus Friedl 161556Srgrimes * Copyright (c) 2000 Markus Friedl. All rights reserved. 171556Srgrimes * 181556Srgrimes * Redistribution and use in source and binary forms, with or without 191556Srgrimes * modification, are permitted provided that the following conditions 201556Srgrimes * are met: 211556Srgrimes * 1. Redistributions of source code must retain the above copyright 221556Srgrimes * notice, this list of conditions and the following disclaimer. 231556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 241556Srgrimes * notice, this list of conditions and the following disclaimer in the 251556Srgrimes * documentation and/or other materials provided with the distribution. 261556Srgrimes * 271556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 281556Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 291556Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 301556Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 311556Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 321556Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3390153Smarkm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 341556Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3527967Ssteve * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3690153Smarkm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3727967Ssteve */ 38114583Smarkm 3999109Sobrien#include "includes.h" 401556SrgrimesRCSID("$OpenBSD: bufaux.c,v 1.25 2002/04/20 09:14:58 markus Exp $"); 411556Srgrimes 421556Srgrimes#include <openssl/bn.h> 431556Srgrimes#include "bufaux.h" 441556Srgrimes#include "xmalloc.h" 4535373Sdes#include "getput.h" 461556Srgrimes#include "log.h" 47128823Stjr 481556Srgrimes/* 491556Srgrimes * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed 501556Srgrimes * by (bits+7)/8 bytes of binary data, msb first. 51128823Stjr */ 52128823Stjrvoid 531556Srgrimesbuffer_put_bignum(Buffer *buffer, BIGNUM *value) 541556Srgrimes{ 551556Srgrimes int bits = BN_num_bits(value); 561556Srgrimes int bin_size = (bits + 7) / 8; 5762597Sassar u_char *buf = xmalloc(bin_size); 58128823Stjr int oi; 59128823Stjr char msg[2]; 60128823Stjr 61128823Stjr /* Get the value of in binary */ 62128823Stjr oi = BN_bn2bin(value, buf); 63128823Stjr if (oi != bin_size) 64128823Stjr fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d", 65128823Stjr oi, bin_size); 66128823Stjr 67128823Stjr /* Store the number of bits in the buffer in two bytes, msb first. */ 68128823Stjr PUT_16BIT(msg, bits); 69128823Stjr buffer_append(buffer, msg, 2); 70128823Stjr /* Store the binary data. */ 71128823Stjr buffer_append(buffer, (char *)buf, oi); 72128823Stjr 73128823Stjr memset(buf, 0, bin_size); 74128823Stjr xfree(buf); 75128823Stjr} 76128823Stjr 77128823Stjr/* 78128823Stjr * Retrieves an BIGNUM from the buffer. 79128823Stjr */ 80128823Stjrvoid 81128823Stjrbuffer_get_bignum(Buffer *buffer, BIGNUM *value) 82128823Stjr{ 83128823Stjr int bits, bytes; 84128823Stjr u_char buf[2], *bin; 85128823Stjr 86128823Stjr /* Get the number for bits. */ 87128823Stjr buffer_get(buffer, (char *) buf, 2); 8890110Simp bits = GET_16BIT(buf); 891556Srgrimes /* Compute the number of binary bytes that follow. */ 90128823Stjr bytes = (bits + 7) / 8; 91128823Stjr if (buffer_len(buffer) < bytes) 92128823Stjr fatal("buffer_get_bignum: input buffer too small"); 93128823Stjr bin = buffer_ptr(buffer); 941556Srgrimes BN_bin2bn(bin, bytes, value); 95128823Stjr buffer_consume(buffer, bytes); 96128823Stjr} 97128823Stjr 98128823Stjr/* 9962597Sassar * Stores an BIGNUM in the buffer in SSH2 format. 100128823Stjr */ 101128823Stjrvoid 102128823Stjrbuffer_put_bignum2(Buffer *buffer, BIGNUM *value) 103128823Stjr{ 104128823Stjr int bytes = BN_num_bytes(value) + 1; 105128823Stjr u_char *buf = xmalloc(bytes); 106128823Stjr int oi; 107128823Stjr int hasnohigh = 0; 108128823Stjr buf[0] = '\0'; 109128823Stjr /* Get the value of in binary */ 110128823Stjr oi = BN_bn2bin(value, buf+1); 111128823Stjr if (oi != bytes-1) 112128823Stjr fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d", 113128823Stjr oi, bytes); 114128823Stjr hasnohigh = (buf[1] & 0x80) ? 0 : 1; 115128823Stjr if (value->neg) { 116128823Stjr /**XXX should be two's-complement */ 117128823Stjr int i, carry; 118128823Stjr u_char *uc = buf; 119128823Stjr log("negativ!"); 120128823Stjr for (i = bytes-1, carry = 1; i>=0; i--) { 121128823Stjr uc[i] ^= 0xff; 1221556Srgrimes if (carry) 1231556Srgrimes carry = !++uc[i]; 12435373Sdes } 12535373Sdes } 12635373Sdes buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); 12735373Sdes memset(buf, 0, bytes); 12835417Sdes xfree(buf); 12935417Sdes} 13035417Sdes 13135417Sdesvoid 13235417Sdesbuffer_get_bignum2(Buffer *buffer, BIGNUM *value) 13335417Sdes{ 13435417Sdes /**XXX should be two's-complement */ 13535373Sdes int len; 13635417Sdes u_char *bin = buffer_get_string(buffer, (u_int *)&len); 13790150Smarkm BN_bin2bn(bin, len, value); 13890110Simp xfree(bin); 13935373Sdes} 140128823Stjr/* 141128823Stjr * Returns integers from the buffer (msb first). 142128823Stjr */ 14335373Sdes 144128823Stjru_short 145128823Stjrbuffer_get_short(Buffer *buffer) 146128823Stjr{ 147128823Stjr u_char buf[2]; 148128823Stjr buffer_get(buffer, (char *) buf, 2); 149128823Stjr return GET_16BIT(buf); 150128823Stjr} 151128823Stjr 152128823Stjru_int 153128823Stjrbuffer_get_int(Buffer *buffer) 154128823Stjr{ 155128823Stjr u_char buf[4]; 156128823Stjr buffer_get(buffer, (char *) buf, 4); 157128823Stjr return GET_32BIT(buf); 158128823Stjr} 159128823Stjr 160128823Stjr#ifdef HAVE_U_INT64_T 161128823Stjru_int64_t 162128823Stjrbuffer_get_int64(Buffer *buffer) 163128823Stjr{ 164128823Stjr u_char buf[8]; 16535373Sdes buffer_get(buffer, (char *) buf, 8); 16635373Sdes return GET_64BIT(buf); 16735373Sdes} 16890110Simp#endif 16935373Sdes 170128823Stjr/* 171128823Stjr * Stores integers in the buffer, msb first. 172128823Stjr */ 173128823Stjrvoid 174128823Stjrbuffer_put_short(Buffer *buffer, u_short value) 175128823Stjr{ 176128823Stjr char buf[2]; 17735373Sdes PUT_16BIT(buf, value); 178128823Stjr buffer_append(buffer, buf, 2); 179128823Stjr} 180128823Stjr 181128823Stjrvoid 182128823Stjrbuffer_put_int(Buffer *buffer, u_int value) 183128823Stjr{ 184128823Stjr char buf[4]; 185128823Stjr PUT_32BIT(buf, value); 186128823Stjr buffer_append(buffer, buf, 4); 187128823Stjr} 188128823Stjr 189128823Stjr#ifdef HAVE_U_INT64_T 190128823Stjrvoid 191128823Stjrbuffer_put_int64(Buffer *buffer, u_int64_t value) 192128823Stjr{ 193128823Stjr char buf[8]; 194128823Stjr PUT_64BIT(buf, value); 195128823Stjr buffer_append(buffer, buf, 8); 196128823Stjr} 197128823Stjr#endif 198128823Stjr 199128823Stjr/* 200128823Stjr * Returns an arbitrary binary string from the buffer. The string cannot 201128823Stjr * be longer than 256k. The returned value points to memory allocated 20235417Sdes * with xmalloc; it is the responsibility of the calling function to free 20340300Sdes * the data. If length_ptr is non-NULL, the length of the returned data 20440300Sdes * will be stored there. A null character will be automatically appended 205128823Stjr * to the returned string, and is not counted in length. 206128823Stjr */ 20735417Sdesvoid * 208128823Stjrbuffer_get_string(Buffer *buffer, u_int *length_ptr) 209128823Stjr{ 210128823Stjr u_int len; 211128823Stjr u_char *value; 212128823Stjr /* Get the length. */ 213128823Stjr len = buffer_get_int(buffer); 214128823Stjr if (len > 256 * 1024) 21535373Sdes fatal("buffer_get_string: bad string length %d", len); 216128823Stjr /* Allocate space for the string. Add one byte for a null character. */ 21735373Sdes value = xmalloc(len + 1); 21835373Sdes /* Get the string. */ 2191556Srgrimes buffer_get(buffer, value, len); 22090110Simp /* Append a null character to make processing easier. */ 2211556Srgrimes value[len] = 0; 22261324Sache /* Optionally return the length of the string. */ 22361324Sache if (length_ptr) 224119914Stjr *length_ptr = len; 22561324Sache return value; 226119914Stjr} 22761324Sache 22835426Sdes/* 2291556Srgrimes * Stores and arbitrary binary string in the buffer. 2301556Srgrimes */ 231void 232buffer_put_string(Buffer *buffer, const void *buf, u_int len) 233{ 234 buffer_put_int(buffer, len); 235 buffer_append(buffer, buf, len); 236} 237void 238buffer_put_cstring(Buffer *buffer, const char *s) 239{ 240 if (s == NULL) 241 fatal("buffer_put_cstring: s == NULL"); 242 buffer_put_string(buffer, s, strlen(s)); 243} 244 245/* 246 * Returns a character from the buffer (0 - 255). 247 */ 248int 249buffer_get_char(Buffer *buffer) 250{ 251 char ch; 252 buffer_get(buffer, &ch, 1); 253 return (u_char) ch; 254} 255 256/* 257 * Stores a character in the buffer. 258 */ 259void 260buffer_put_char(Buffer *buffer, int value) 261{ 262 char ch = value; 263 buffer_append(buffer, &ch, 1); 264} 265