Annotation of src/usr.bin/ssh/bufbn.c, Revision 1.11
1.11 ! djm 1: /* $OpenBSD: bufbn.c,v 1.10 2014/02/27 00:41:49 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:
1.9 djm 81: explicit_bzero(buf, 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);
1.11 ! djm 109: if (bits > 65535-7) {
1.10 djm 110: error("buffer_get_bignum_ret: cannot handle BN of size %d",
111: bits);
112: return (-1);
113: }
1.1 dtucker 114: /* Compute the number of binary bytes that follow. */
115: bytes = (bits + 7) / 8;
116: if (bytes > 8 * 1024) {
117: error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
118: return (-1);
119: }
120: if (buffer_len(buffer) < bytes) {
121: error("buffer_get_bignum_ret: input buffer too small");
122: return (-1);
123: }
124: bin = buffer_ptr(buffer);
1.4 markus 125: if (BN_bin2bn(bin, bytes, value) == NULL) {
126: error("buffer_get_bignum_ret: BN_bin2bn failed");
127: return (-1);
128: }
1.1 dtucker 129: if (buffer_consume_ret(buffer, bytes) == -1) {
130: error("buffer_get_bignum_ret: buffer_consume failed");
131: return (-1);
132: }
133: return (0);
134: }
135:
136: void
137: buffer_get_bignum(Buffer *buffer, BIGNUM *value)
138: {
139: if (buffer_get_bignum_ret(buffer, value) == -1)
140: fatal("buffer_get_bignum: buffer error");
141: }
142:
143: /*
1.5 stevesk 144: * Stores a BIGNUM in the buffer in SSH2 format.
1.1 dtucker 145: */
146: int
147: buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
148: {
149: u_int bytes;
150: u_char *buf;
151: int oi;
152: u_int hasnohigh = 0;
153:
154: if (BN_is_zero(value)) {
155: buffer_put_int(buffer, 0);
156: return 0;
157: }
158: if (value->neg) {
159: error("buffer_put_bignum2_ret: negative numbers not supported");
160: return (-1);
161: }
162: bytes = BN_num_bytes(value) + 1; /* extra padding byte */
163: if (bytes < 2) {
164: error("buffer_put_bignum2_ret: BN too small");
165: return (-1);
166: }
167: buf = xmalloc(bytes);
168: buf[0] = 0x00;
169: /* Get the value of in binary */
170: oi = BN_bn2bin(value, buf+1);
171: if (oi < 0 || (u_int)oi != bytes - 1) {
172: error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
173: "oi %d != bin_size %d", oi, bytes);
1.7 djm 174: free(buf);
1.1 dtucker 175: return (-1);
176: }
177: hasnohigh = (buf[1] & 0x80) ? 0 : 1;
178: buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
1.9 djm 179: explicit_bzero(buf, bytes);
1.7 djm 180: free(buf);
1.1 dtucker 181: return (0);
182: }
183:
184: void
185: buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
186: {
187: if (buffer_put_bignum2_ret(buffer, value) == -1)
188: fatal("buffer_put_bignum2: buffer error");
189: }
190:
191: int
192: buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
193: {
194: u_int len;
195: u_char *bin;
196:
197: if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
198: error("buffer_get_bignum2_ret: invalid bignum");
199: return (-1);
200: }
201:
202: if (len > 0 && (bin[0] & 0x80)) {
203: error("buffer_get_bignum2_ret: negative numbers not supported");
1.7 djm 204: free(bin);
1.1 dtucker 205: return (-1);
206: }
207: if (len > 8 * 1024) {
1.6 djm 208: error("buffer_get_bignum2_ret: cannot handle BN of size %d",
209: len);
1.7 djm 210: free(bin);
1.1 dtucker 211: return (-1);
212: }
1.4 markus 213: if (BN_bin2bn(bin, len, value) == NULL) {
214: error("buffer_get_bignum2_ret: BN_bin2bn failed");
1.7 djm 215: free(bin);
1.4 markus 216: return (-1);
217: }
1.7 djm 218: free(bin);
1.1 dtucker 219: return (0);
220: }
221:
222: void
223: buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
224: {
225: if (buffer_get_bignum2_ret(buffer, value) == -1)
226: fatal("buffer_get_bignum2: buffer error");
227: }