diff options
author | Damien Miller <djm@mindrot.org> | 2014-05-15 14:33:43 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-05-15 14:33:43 +1000 |
commit | 05e82c3b963c33048128baf72a6f6b3a1c10b4c1 (patch) | |
tree | cb238452459af2f8311d54ca509722497e799517 /bufaux.c | |
parent | 380948180f847a26f2d0c85b4dad3dca2ed2fd8b (diff) |
- djm@cvs.openbsd.org 2014/04/30 05:29:56
[bufaux.c bufbn.c bufec.c buffer.c buffer.h sshbuf-getput-basic.c]
[sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c sshbuf.h ssherr.c]
[ssherr.h]
New buffer API; the first installment of the conversion/replacement
of OpenSSH's internals to make them usable as a standalone library.
This includes a set of wrappers to make it compatible with the
existing buffer API so replacement can occur incrementally.
With and ok markus@
Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew
Dempsky and Ron Bowes for a detailed review.
Diffstat (limited to 'bufaux.c')
-rw-r--r-- | bufaux.c | 332 |
1 files changed, 99 insertions, 233 deletions
@@ -1,68 +1,38 @@ | |||
1 | /* $OpenBSD: bufaux.c,v 1.59 2014/04/29 18:01:49 markus Exp $ */ | 1 | /* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Copyright (c) 2012 Damien Miller <djm@mindrot.org> |
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 | * | 4 | * |
9 | * As far as I am concerned, the code I have written for this software | 5 | * Permission to use, copy, modify, and distribute this software for any |
10 | * can be used freely for any purpose. Any derived versions of this | 6 | * purpose with or without fee is hereby granted, provided that the above |
11 | * software must be clearly marked as such, and if the derived work is | 7 | * copyright notice and this permission notice appear in all copies. |
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 | * | 8 | * |
15 | * | 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
16 | * SSH2 packet format added by Markus Friedl | 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
17 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
18 | * | 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
19 | * Redistribution and use in source and binary forms, with or without | 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
20 | * modification, are permitted provided that the following conditions | 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
21 | * are met: | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
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 | */ | 16 | */ |
39 | 17 | ||
40 | #include "includes.h" | 18 | /* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ |
41 | 19 | ||
42 | #include <sys/types.h> | 20 | #include <sys/types.h> |
43 | 21 | ||
44 | #include <string.h> | ||
45 | #include <stdarg.h> | ||
46 | #include <stdlib.h> | ||
47 | |||
48 | #include "xmalloc.h" | ||
49 | #include "buffer.h" | 22 | #include "buffer.h" |
50 | #include "log.h" | 23 | #include "log.h" |
51 | #include "misc.h" | 24 | #include "ssherr.h" |
52 | |||
53 | /* | ||
54 | * Returns integers from the buffer (msb first). | ||
55 | */ | ||
56 | 25 | ||
57 | int | 26 | int |
58 | buffer_get_short_ret(u_short *ret, Buffer *buffer) | 27 | buffer_get_short_ret(u_short *v, Buffer *buffer) |
59 | { | 28 | { |
60 | u_char buf[2]; | 29 | int ret; |
61 | 30 | ||
62 | if (buffer_get_ret(buffer, (char *) buf, 2) == -1) | 31 | if ((ret = sshbuf_get_u16(buffer, v)) != 0) { |
63 | return (-1); | 32 | error("%s: %s", __func__, ssh_err(ret)); |
64 | *ret = get_u16(buf); | 33 | return -1; |
65 | return (0); | 34 | } |
35 | return 0; | ||
66 | } | 36 | } |
67 | 37 | ||
68 | u_short | 38 | u_short |
@@ -71,21 +41,21 @@ buffer_get_short(Buffer *buffer) | |||
71 | u_short ret; | 41 | u_short ret; |
72 | 42 | ||
73 | if (buffer_get_short_ret(&ret, buffer) == -1) | 43 | if (buffer_get_short_ret(&ret, buffer) == -1) |
74 | fatal("buffer_get_short: buffer error"); | 44 | fatal("%s: buffer error", __func__); |
75 | 45 | ||
76 | return (ret); | 46 | return (ret); |
77 | } | 47 | } |
78 | 48 | ||
79 | int | 49 | int |
80 | buffer_get_int_ret(u_int *ret, Buffer *buffer) | 50 | buffer_get_int_ret(u_int *v, Buffer *buffer) |
81 | { | 51 | { |
82 | u_char buf[4]; | 52 | int ret; |
83 | 53 | ||
84 | if (buffer_get_ret(buffer, (char *) buf, 4) == -1) | 54 | if ((ret = sshbuf_get_u32(buffer, v)) != 0) { |
85 | return (-1); | 55 | error("%s: %s", __func__, ssh_err(ret)); |
86 | if (ret != NULL) | 56 | return -1; |
87 | *ret = get_u32(buf); | 57 | } |
88 | return (0); | 58 | return 0; |
89 | } | 59 | } |
90 | 60 | ||
91 | u_int | 61 | u_int |
@@ -94,21 +64,21 @@ buffer_get_int(Buffer *buffer) | |||
94 | u_int ret; | 64 | u_int ret; |
95 | 65 | ||
96 | if (buffer_get_int_ret(&ret, buffer) == -1) | 66 | if (buffer_get_int_ret(&ret, buffer) == -1) |
97 | fatal("buffer_get_int: buffer error"); | 67 | fatal("%s: buffer error", __func__); |
98 | 68 | ||
99 | return (ret); | 69 | return (ret); |
100 | } | 70 | } |
101 | 71 | ||
102 | int | 72 | int |
103 | buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) | 73 | buffer_get_int64_ret(u_int64_t *v, Buffer *buffer) |
104 | { | 74 | { |
105 | u_char buf[8]; | 75 | int ret; |
106 | 76 | ||
107 | if (buffer_get_ret(buffer, (char *) buf, 8) == -1) | 77 | if ((ret = sshbuf_get_u64(buffer, v)) != 0) { |
108 | return (-1); | 78 | error("%s: %s", __func__, ssh_err(ret)); |
109 | if (ret != NULL) | 79 | return -1; |
110 | *ret = get_u64(buf); | 80 | } |
111 | return (0); | 81 | return 0; |
112 | } | 82 | } |
113 | 83 | ||
114 | u_int64_t | 84 | u_int64_t |
@@ -117,78 +87,52 @@ buffer_get_int64(Buffer *buffer) | |||
117 | u_int64_t ret; | 87 | u_int64_t ret; |
118 | 88 | ||
119 | if (buffer_get_int64_ret(&ret, buffer) == -1) | 89 | if (buffer_get_int64_ret(&ret, buffer) == -1) |
120 | fatal("buffer_get_int: buffer error"); | 90 | fatal("%s: buffer error", __func__); |
121 | 91 | ||
122 | return (ret); | 92 | return (ret); |
123 | } | 93 | } |
124 | 94 | ||
125 | /* | ||
126 | * Stores integers in the buffer, msb first. | ||
127 | */ | ||
128 | void | 95 | void |
129 | buffer_put_short(Buffer *buffer, u_short value) | 96 | buffer_put_short(Buffer *buffer, u_short value) |
130 | { | 97 | { |
131 | char buf[2]; | 98 | int ret; |
132 | 99 | ||
133 | put_u16(buf, value); | 100 | if ((ret = sshbuf_put_u16(buffer, value)) != 0) |
134 | buffer_append(buffer, buf, 2); | 101 | fatal("%s: %s", __func__, ssh_err(ret)); |
135 | } | 102 | } |
136 | 103 | ||
137 | void | 104 | void |
138 | buffer_put_int(Buffer *buffer, u_int value) | 105 | buffer_put_int(Buffer *buffer, u_int value) |
139 | { | 106 | { |
140 | char buf[4]; | 107 | int ret; |
141 | 108 | ||
142 | put_u32(buf, value); | 109 | if ((ret = sshbuf_put_u32(buffer, value)) != 0) |
143 | buffer_append(buffer, buf, 4); | 110 | fatal("%s: %s", __func__, ssh_err(ret)); |
144 | } | 111 | } |
145 | 112 | ||
146 | void | 113 | void |
147 | buffer_put_int64(Buffer *buffer, u_int64_t value) | 114 | buffer_put_int64(Buffer *buffer, u_int64_t value) |
148 | { | 115 | { |
149 | char buf[8]; | 116 | int ret; |
150 | 117 | ||
151 | put_u64(buf, value); | 118 | if ((ret = sshbuf_put_u64(buffer, value)) != 0) |
152 | buffer_append(buffer, buf, 8); | 119 | fatal("%s: %s", __func__, ssh_err(ret)); |
153 | } | 120 | } |
154 | 121 | ||
155 | /* | ||
156 | * Returns an arbitrary binary string from the buffer. The string cannot | ||
157 | * be longer than 256k. The returned value points to memory allocated | ||
158 | * with xmalloc; it is the responsibility of the calling function to free | ||
159 | * the data. If length_ptr is non-NULL, the length of the returned data | ||
160 | * will be stored there. A null character will be automatically appended | ||
161 | * to the returned string, and is not counted in length. | ||
162 | */ | ||
163 | void * | 122 | void * |
164 | buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) | 123 | buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) |
165 | { | 124 | { |
125 | size_t len; | ||
126 | int ret; | ||
166 | u_char *value; | 127 | u_char *value; |
167 | u_int len; | ||
168 | 128 | ||
169 | /* Get the length. */ | 129 | if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) { |
170 | if (buffer_get_int_ret(&len, buffer) != 0) { | 130 | error("%s: %s", __func__, ssh_err(ret)); |
171 | error("buffer_get_string_ret: cannot extract length"); | 131 | return NULL; |
172 | return (NULL); | ||
173 | } | ||
174 | if (len > 256 * 1024) { | ||
175 | error("buffer_get_string_ret: bad string length %u", len); | ||
176 | return (NULL); | ||
177 | } | ||
178 | /* Allocate space for the string. Add one byte for a null character. */ | ||
179 | value = xmalloc(len + 1); | ||
180 | /* Get the string. */ | ||
181 | if (buffer_get_ret(buffer, value, len) == -1) { | ||
182 | error("buffer_get_string_ret: buffer_get failed"); | ||
183 | free(value); | ||
184 | return (NULL); | ||
185 | } | 132 | } |
186 | /* Append a null character to make processing easier. */ | 133 | if (length_ptr != NULL) |
187 | value[len] = '\0'; | 134 | *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ |
188 | /* Optionally return the length of the string. */ | 135 | return value; |
189 | if (length_ptr) | ||
190 | *length_ptr = len; | ||
191 | return (value); | ||
192 | } | 136 | } |
193 | 137 | ||
194 | void * | 138 | void * |
@@ -197,31 +141,24 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr) | |||
197 | void *ret; | 141 | void *ret; |
198 | 142 | ||
199 | if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) | 143 | if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) |
200 | fatal("buffer_get_string: buffer error"); | 144 | fatal("%s: buffer error", __func__); |
201 | return (ret); | 145 | return (ret); |
202 | } | 146 | } |
203 | 147 | ||
204 | char * | 148 | char * |
205 | buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) | 149 | buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) |
206 | { | 150 | { |
207 | u_int length; | 151 | size_t len; |
208 | char *cp, *ret = buffer_get_string_ret(buffer, &length); | 152 | int ret; |
153 | char *value; | ||
209 | 154 | ||
210 | if (ret == NULL) | 155 | if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) { |
156 | error("%s: %s", __func__, ssh_err(ret)); | ||
211 | return NULL; | 157 | return NULL; |
212 | if ((cp = memchr(ret, '\0', length)) != NULL) { | ||
213 | /* XXX allow \0 at end-of-string for a while, remove later */ | ||
214 | if (cp == ret + length - 1) | ||
215 | error("buffer_get_cstring_ret: string contains \\0"); | ||
216 | else { | ||
217 | explicit_bzero(ret, length); | ||
218 | free(ret); | ||
219 | return NULL; | ||
220 | } | ||
221 | } | 158 | } |
222 | if (length_ptr != NULL) | 159 | if (length_ptr != NULL) |
223 | *length_ptr = length; | 160 | *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ |
224 | return ret; | 161 | return value; |
225 | } | 162 | } |
226 | 163 | ||
227 | char * | 164 | char * |
@@ -230,27 +167,24 @@ buffer_get_cstring(Buffer *buffer, u_int *length_ptr) | |||
230 | char *ret; | 167 | char *ret; |
231 | 168 | ||
232 | if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) | 169 | if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) |
233 | fatal("buffer_get_cstring: buffer error"); | 170 | fatal("%s: buffer error", __func__); |
234 | return ret; | 171 | return ret; |
235 | } | 172 | } |
236 | 173 | ||
237 | const void * | 174 | const void * |
238 | buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) | 175 | buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) |
239 | { | 176 | { |
240 | void *ptr; | 177 | size_t len; |
241 | u_int len; | 178 | int ret; |
179 | const u_char *value; | ||
242 | 180 | ||
243 | if (buffer_get_int_ret(&len, buffer) != 0) | 181 | if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) { |
244 | return NULL; | 182 | error("%s: %s", __func__, ssh_err(ret)); |
245 | if (len > 256 * 1024) { | ||
246 | error("buffer_get_string_ptr: bad string length %u", len); | ||
247 | return NULL; | 183 | return NULL; |
248 | } | 184 | } |
249 | ptr = buffer_ptr(buffer); | 185 | if (length_ptr != NULL) |
250 | buffer_consume(buffer, len); | 186 | *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ |
251 | if (length_ptr) | 187 | return value; |
252 | *length_ptr = len; | ||
253 | return (ptr); | ||
254 | } | 188 | } |
255 | 189 | ||
256 | const void * | 190 | const void * |
@@ -259,133 +193,65 @@ buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) | |||
259 | const void *ret; | 193 | const void *ret; |
260 | 194 | ||
261 | if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) | 195 | if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) |
262 | fatal("buffer_get_string_ptr: buffer error"); | 196 | fatal("%s: buffer error", __func__); |
263 | return (ret); | 197 | return (ret); |
264 | } | 198 | } |
265 | 199 | ||
266 | /* | ||
267 | * Stores and arbitrary binary string in the buffer. | ||
268 | */ | ||
269 | void | 200 | void |
270 | buffer_put_string(Buffer *buffer, const void *buf, u_int len) | 201 | buffer_put_string(Buffer *buffer, const void *buf, u_int len) |
271 | { | 202 | { |
272 | buffer_put_int(buffer, len); | 203 | int ret; |
273 | buffer_append(buffer, buf, len); | 204 | |
205 | if ((ret = sshbuf_put_string(buffer, buf, len)) != 0) | ||
206 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
274 | } | 207 | } |
208 | |||
275 | void | 209 | void |
276 | buffer_put_cstring(Buffer *buffer, const char *s) | 210 | buffer_put_cstring(Buffer *buffer, const char *s) |
277 | { | 211 | { |
278 | if (s == NULL) | 212 | int ret; |
279 | fatal("buffer_put_cstring: s == NULL"); | 213 | |
280 | buffer_put_string(buffer, s, strlen(s)); | 214 | if ((ret = sshbuf_put_cstring(buffer, s)) != 0) |
215 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
281 | } | 216 | } |
282 | 217 | ||
283 | /* | ||
284 | * Returns a character from the buffer (0 - 255). | ||
285 | */ | ||
286 | int | 218 | int |
287 | buffer_get_char_ret(u_char *ret, Buffer *buffer) | 219 | buffer_get_char_ret(char *v, Buffer *buffer) |
288 | { | 220 | { |
289 | if (buffer_get_ret(buffer, ret, 1) == -1) { | 221 | int ret; |
290 | error("buffer_get_char_ret: buffer_get_ret failed"); | 222 | |
291 | return (-1); | 223 | if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) { |
224 | error("%s: %s", __func__, ssh_err(ret)); | ||
225 | return -1; | ||
292 | } | 226 | } |
293 | return (0); | 227 | return 0; |
294 | } | 228 | } |
295 | 229 | ||
296 | int | 230 | int |
297 | buffer_get_char(Buffer *buffer) | 231 | buffer_get_char(Buffer *buffer) |
298 | { | 232 | { |
299 | u_char ch; | 233 | char ch; |
300 | 234 | ||
301 | if (buffer_get_char_ret(&ch, buffer) == -1) | 235 | if (buffer_get_char_ret(&ch, buffer) == -1) |
302 | fatal("buffer_get_char: buffer error"); | 236 | fatal("%s: buffer error", __func__); |
303 | return ch; | 237 | return (u_char) ch; |
304 | } | 238 | } |
305 | 239 | ||
306 | /* | ||
307 | * Stores a character in the buffer. | ||
308 | */ | ||
309 | void | 240 | void |
310 | buffer_put_char(Buffer *buffer, int value) | 241 | buffer_put_char(Buffer *buffer, int value) |
311 | { | 242 | { |
312 | char ch = value; | 243 | int ret; |
313 | |||
314 | buffer_append(buffer, &ch, 1); | ||
315 | } | ||
316 | |||
317 | /* Pseudo bignum functions */ | ||
318 | |||
319 | void * | ||
320 | buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr) | ||
321 | { | ||
322 | u_int len; | ||
323 | u_char *bin, *p, *ret; | ||
324 | |||
325 | if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) { | ||
326 | error("%s: invalid bignum", __func__); | ||
327 | return NULL; | ||
328 | } | ||
329 | |||
330 | if (len > 0 && (bin[0] & 0x80)) { | ||
331 | error("%s: negative numbers not supported", __func__); | ||
332 | free(bin); | ||
333 | return NULL; | ||
334 | } | ||
335 | if (len > 8 * 1024) { | ||
336 | error("%s: cannot handle BN of size %d", __func__, len); | ||
337 | free(bin); | ||
338 | return NULL; | ||
339 | } | ||
340 | /* Skip zero prefix on numbers with the MSB set */ | ||
341 | if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) { | ||
342 | p++; | ||
343 | len--; | ||
344 | } | ||
345 | ret = xmalloc(len); | ||
346 | memcpy(ret, p, len); | ||
347 | explicit_bzero(p, len); | ||
348 | free(bin); | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | void * | ||
353 | buffer_get_bignum2_as_string(Buffer *buffer, u_int *l) | ||
354 | { | ||
355 | void *ret = buffer_get_bignum2_as_string_ret(buffer, l); | ||
356 | 244 | ||
357 | if (ret == NULL) | 245 | if ((ret = sshbuf_put_u8(buffer, value)) != 0) |
358 | fatal("%s: buffer error", __func__); | 246 | fatal("%s: %s", __func__, ssh_err(ret)); |
359 | return ret; | ||
360 | } | 247 | } |
361 | 248 | ||
362 | /* | ||
363 | * Stores a string using the bignum encoding rules (\0 pad if MSB set). | ||
364 | */ | ||
365 | void | 249 | void |
366 | buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) | 250 | buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) |
367 | { | 251 | { |
368 | u_char *buf, *p; | 252 | int ret; |
369 | int pad = 0; | ||
370 | |||
371 | if (l > 8 * 1024) | ||
372 | fatal("%s: length %u too long", __func__, l); | ||
373 | /* Skip leading zero bytes */ | ||
374 | for (; l > 0 && *s == 0; l--, s++) | ||
375 | ; | ||
376 | p = buf = xmalloc(l + 1); | ||
377 | /* | ||
378 | * If most significant bit is set then prepend a zero byte to | ||
379 | * avoid interpretation as a negative number. | ||
380 | */ | ||
381 | if (l > 0 && (s[0] & 0x80) != 0) { | ||
382 | *p++ = '\0'; | ||
383 | pad = 1; | ||
384 | } | ||
385 | memcpy(p, s, l); | ||
386 | buffer_put_string(buffer, buf, l + pad); | ||
387 | explicit_bzero(buf, l + pad); | ||
388 | free(buf); | ||
389 | } | ||
390 | 253 | ||
254 | if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0) | ||
255 | fatal("%s: %s", __func__, ssh_err(ret)); | ||
256 | } | ||
391 | 257 | ||