Annotation of src/usr.bin/ssh/bufbn.c, Revision 1.8
1.8 ! dtucker 1: /* $OpenBSD: bufbn.c,v 1.7 2013/05/17 00:13:13 djm 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.8 ! dtucker 46: #include <stdlib.h>
1.2 stevesk 47:
1.1 dtucker 48: #include "xmalloc.h"
1.3 deraadt 49: #include "buffer.h"
1.1 dtucker 50: #include "log.h"
51: #include "misc.h"
52:
53: /*
54: * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
55: * by (bits+7)/8 bytes of binary data, msb first.
56: */
57: int
58: buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
59: {
60: int bits = BN_num_bits(value);
61: int bin_size = (bits + 7) / 8;
62: u_char *buf = xmalloc(bin_size);
63: int oi;
64: char msg[2];
65:
66: /* Get the value of in binary */
67: oi = BN_bn2bin(value, buf);
68: if (oi != bin_size) {
69: error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
70: oi, bin_size);
1.7 djm 71: free(buf);
1.1 dtucker 72: return (-1);
73: }
74:
75: /* Store the number of bits in the buffer in two bytes, msb first. */
76: put_u16(msg, bits);
77: buffer_append(buffer, msg, 2);
78: /* Store the binary data. */
79: buffer_append(buffer, buf, oi);
80:
81: memset(buf, 0, bin_size);
1.7 djm 82: free(buf);
1.1 dtucker 83:
84: return (0);
85: }
86:
87: void
88: buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
89: {
90: if (buffer_put_bignum_ret(buffer, value) == -1)
91: fatal("buffer_put_bignum: buffer error");
92: }
93:
94: /*
1.5 stevesk 95: * Retrieves a BIGNUM from the buffer.
1.1 dtucker 96: */
97: int
98: buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
99: {
100: u_int bits, bytes;
101: u_char buf[2], *bin;
102:
1.5 stevesk 103: /* Get the number of bits. */
1.1 dtucker 104: if (buffer_get_ret(buffer, (char *) buf, 2) == -1) {
105: error("buffer_get_bignum_ret: invalid length");
106: return (-1);
107: }
108: bits = get_u16(buf);
109: /* Compute the number of binary bytes that follow. */
110: bytes = (bits + 7) / 8;
111: if (bytes > 8 * 1024) {
112: error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
113: return (-1);
114: }
115: if (buffer_len(buffer) < bytes) {
116: error("buffer_get_bignum_ret: input buffer too small");
117: return (-1);
118: }
119: bin = buffer_ptr(buffer);
1.4 markus 120: if (BN_bin2bn(bin, bytes, value) == NULL) {
121: error("buffer_get_bignum_ret: BN_bin2bn failed");
122: return (-1);
123: }
1.1 dtucker 124: if (buffer_consume_ret(buffer, bytes) == -1) {
125: error("buffer_get_bignum_ret: buffer_consume failed");
126: return (-1);
127: }
128: return (0);
129: }
130:
131: void
132: buffer_get_bignum(Buffer *buffer, BIGNUM *value)
133: {
134: if (buffer_get_bignum_ret(buffer, value) == -1)
135: fatal("buffer_get_bignum: buffer error");
136: }
137:
138: /*
1.5 stevesk 139: * Stores a BIGNUM in the buffer in SSH2 format.
1.1 dtucker 140: */
141: int
142: buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
143: {
144: u_int bytes;
145: u_char *buf;
146: int oi;
147: u_int hasnohigh = 0;
148:
149: if (BN_is_zero(value)) {
150: buffer_put_int(buffer, 0);
151: return 0;
152: }
153: if (value->neg) {
154: error("buffer_put_bignum2_ret: negative numbers not supported");
155: return (-1);
156: }
157: bytes = BN_num_bytes(value) + 1; /* extra padding byte */
158: if (bytes < 2) {
159: error("buffer_put_bignum2_ret: BN too small");
160: return (-1);
161: }
162: buf = xmalloc(bytes);
163: buf[0] = 0x00;
164: /* Get the value of in binary */
165: oi = BN_bn2bin(value, buf+1);
166: if (oi < 0 || (u_int)oi != bytes - 1) {
167: error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
168: "oi %d != bin_size %d", oi, bytes);
1.7 djm 169: free(buf);
1.1 dtucker 170: return (-1);
171: }
172: hasnohigh = (buf[1] & 0x80) ? 0 : 1;
173: buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
174: memset(buf, 0, bytes);
1.7 djm 175: free(buf);
1.1 dtucker 176: return (0);
177: }
178:
179: void
180: buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
181: {
182: if (buffer_put_bignum2_ret(buffer, value) == -1)
183: fatal("buffer_put_bignum2: buffer error");
184: }
185:
186: int
187: buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
188: {
189: u_int len;
190: u_char *bin;
191:
192: if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
193: error("buffer_get_bignum2_ret: invalid bignum");
194: return (-1);
195: }
196:
197: if (len > 0 && (bin[0] & 0x80)) {
198: error("buffer_get_bignum2_ret: negative numbers not supported");
1.7 djm 199: free(bin);
1.1 dtucker 200: return (-1);
201: }
202: if (len > 8 * 1024) {
1.6 djm 203: error("buffer_get_bignum2_ret: cannot handle BN of size %d",
204: len);
1.7 djm 205: free(bin);
1.1 dtucker 206: return (-1);
207: }
1.4 markus 208: if (BN_bin2bn(bin, len, value) == NULL) {
209: error("buffer_get_bignum2_ret: BN_bin2bn failed");
1.7 djm 210: free(bin);
1.4 markus 211: return (-1);
212: }
1.7 djm 213: free(bin);
1.1 dtucker 214: return (0);
215: }
216:
217: void
218: buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
219: {
220: if (buffer_get_bignum2_ret(buffer, value) == -1)
221: fatal("buffer_get_bignum2: buffer error");
222: }