Annotation of src/usr.bin/ssh/bufbn.c, Revision 1.3
1.3 ! deraadt 1: /* $OpenBSD: bufbn.c,v 1.2 2006/07/22 20:48:22 stevesk Exp $*/
1.1 dtucker 2: /*
3: * Author: Tatu Ylonen <ylo@cs.hut.fi>
4: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5: * All rights reserved
6: * Auxiliary functions for storing and retrieving various data types to/from
7: * Buffers.
8: *
9: * As far as I am concerned, the code I have written for this software
10: * can be used freely for any purpose. Any derived versions of this
11: * software must be clearly marked as such, and if the derived work is
12: * incompatible with the protocol description in the RFC file, it must be
13: * called by a name other than "ssh" or "Secure Shell".
14: *
15: *
16: * SSH2 packet format added by Markus Friedl
17: * Copyright (c) 2000 Markus Friedl. All rights reserved.
18: *
19: * Redistribution and use in source and binary forms, with or without
20: * modification, are permitted provided that the following conditions
21: * are met:
22: * 1. Redistributions of source code must retain the above copyright
23: * notice, this list of conditions and the following disclaimer.
24: * 2. Redistributions in binary form must reproduce the above copyright
25: * notice, this list of conditions and the following disclaimer in the
26: * documentation and/or other materials provided with the distribution.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38: */
39:
1.3 ! deraadt 40: #include <sys/types.h>
1.1 dtucker 41:
42: #include <openssl/bn.h>
1.2 stevesk 43:
44: #include <string.h>
1.3 ! deraadt 45: #include <stdarg.h>
1.2 stevesk 46:
1.1 dtucker 47: #include "xmalloc.h"
1.3 ! deraadt 48: #include "buffer.h"
1.1 dtucker 49: #include "log.h"
50: #include "misc.h"
51:
52: /*
53: * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
54: * by (bits+7)/8 bytes of binary data, msb first.
55: */
56: int
57: buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
58: {
59: int bits = BN_num_bits(value);
60: int bin_size = (bits + 7) / 8;
61: u_char *buf = xmalloc(bin_size);
62: int oi;
63: char msg[2];
64:
65: /* Get the value of in binary */
66: oi = BN_bn2bin(value, buf);
67: if (oi != bin_size) {
68: error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
69: oi, bin_size);
70: xfree(buf);
71: return (-1);
72: }
73:
74: /* Store the number of bits in the buffer in two bytes, msb first. */
75: put_u16(msg, bits);
76: buffer_append(buffer, msg, 2);
77: /* Store the binary data. */
78: buffer_append(buffer, buf, oi);
79:
80: memset(buf, 0, bin_size);
81: xfree(buf);
82:
83: return (0);
84: }
85:
86: void
87: buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
88: {
89: if (buffer_put_bignum_ret(buffer, value) == -1)
90: fatal("buffer_put_bignum: buffer error");
91: }
92:
93: /*
94: * Retrieves an BIGNUM from the buffer.
95: */
96: int
97: buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
98: {
99: u_int bits, bytes;
100: u_char buf[2], *bin;
101:
102: /* Get the number for bits. */
103: if (buffer_get_ret(buffer, (char *) buf, 2) == -1) {
104: error("buffer_get_bignum_ret: invalid length");
105: return (-1);
106: }
107: bits = get_u16(buf);
108: /* Compute the number of binary bytes that follow. */
109: bytes = (bits + 7) / 8;
110: if (bytes > 8 * 1024) {
111: error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
112: return (-1);
113: }
114: if (buffer_len(buffer) < bytes) {
115: error("buffer_get_bignum_ret: input buffer too small");
116: return (-1);
117: }
118: bin = buffer_ptr(buffer);
119: BN_bin2bn(bin, bytes, value);
120: if (buffer_consume_ret(buffer, bytes) == -1) {
121: error("buffer_get_bignum_ret: buffer_consume failed");
122: return (-1);
123: }
124: return (0);
125: }
126:
127: void
128: buffer_get_bignum(Buffer *buffer, BIGNUM *value)
129: {
130: if (buffer_get_bignum_ret(buffer, value) == -1)
131: fatal("buffer_get_bignum: buffer error");
132: }
133:
134: /*
135: * Stores an BIGNUM in the buffer in SSH2 format.
136: */
137: int
138: buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
139: {
140: u_int bytes;
141: u_char *buf;
142: int oi;
143: u_int hasnohigh = 0;
144:
145: if (BN_is_zero(value)) {
146: buffer_put_int(buffer, 0);
147: return 0;
148: }
149: if (value->neg) {
150: error("buffer_put_bignum2_ret: negative numbers not supported");
151: return (-1);
152: }
153: bytes = BN_num_bytes(value) + 1; /* extra padding byte */
154: if (bytes < 2) {
155: error("buffer_put_bignum2_ret: BN too small");
156: return (-1);
157: }
158: buf = xmalloc(bytes);
159: buf[0] = 0x00;
160: /* Get the value of in binary */
161: oi = BN_bn2bin(value, buf+1);
162: if (oi < 0 || (u_int)oi != bytes - 1) {
163: error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
164: "oi %d != bin_size %d", oi, bytes);
165: xfree(buf);
166: return (-1);
167: }
168: hasnohigh = (buf[1] & 0x80) ? 0 : 1;
169: buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
170: memset(buf, 0, bytes);
171: xfree(buf);
172: return (0);
173: }
174:
175: void
176: buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
177: {
178: if (buffer_put_bignum2_ret(buffer, value) == -1)
179: fatal("buffer_put_bignum2: buffer error");
180: }
181:
182: int
183: buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
184: {
185: u_int len;
186: u_char *bin;
187:
188: if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
189: error("buffer_get_bignum2_ret: invalid bignum");
190: return (-1);
191: }
192:
193: if (len > 0 && (bin[0] & 0x80)) {
194: error("buffer_get_bignum2_ret: negative numbers not supported");
195: xfree(bin);
196: return (-1);
197: }
198: if (len > 8 * 1024) {
199: error("buffer_get_bignum2_ret: cannot handle BN of size %d", len);
200: xfree(bin);
201: return (-1);
202: }
203: BN_bin2bn(bin, len, value);
204: xfree(bin);
205: return (0);
206: }
207:
208: void
209: buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
210: {
211: if (buffer_get_bignum2_ret(buffer, value) == -1)
212: fatal("buffer_get_bignum2: buffer error");
213: }